Bug #39693 error reporting for mysql_library_init
Submitted: 26 Sep 2008 21:25 Modified: 29 May 2012 19:11
Reporter: Ian Monroe Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Embedded Library ( libmysqld ) Severity:S3 (Non-critical)
Version:5.1, 5.5, 5.6 OS:Any
Assigned to: CPU Architecture:Any

[26 Sep 2008 21:25] Ian Monroe
Description:
If you run `/usr/sbin/mysqld --hasdf` it will give a nice message like:
080926 16:11:20 [ERROR] /usr/sbin/mysqld: unknown option '--hasdf'

However the embedded library does give any indication what goes wrong when it returns 1 from mysql_library_init. A dev actually had to debug step-by-step to see that --skip-innodb wasn't supported by his mysql which was causing mysql_library_init to bail out.

Currently there's a user who is also receiving a 1 on mysql_library_init. They don't have any errant options. Its going to be really hard to figure out what is wrong.

How to repeat:
The following code will crash, since mysql_library_init returns 1 due to the bad options.

    static const int num_elements = 5;
    char **server_options = new char* [ num_elements + 1 ];
    server_options[0] = "amarokmysqld";
    server_options[1] = "--notoption";
    server_options[2] = "--asdfwer";
    server_options[3] = "--default-storage-engine=MYISAM";
    server_options[4] = "--skip-innodb";
    server_options[5] = 0;

    char **server_groups = new char* [ 3 ];
    server_groups[0] = "amarokserver";
    server_groups[1] = "amarokclient";
    server_groups[2] = 0;

    mysql_library_init(num_elements, server_options, server_groups);
    m_db = mysql_init(NULL);

Suggested fix:
Embedded mysql should send error messages to stderr like the mysqld process does.

Alternatively it could return an error code with more meaning then 1.
[27 Sep 2008 15:35] Sveta Smirnova
Thank you for taking the time to write to us, but this is not a bug. Please double-check the documentation available at http://dev.mysql.com/doc/ and the instructions on
how to report a bug at http://bugs.mysql.com/how-to-report.php

You should check errors in your application. For example:

if (int OK = mysql_library_init(num_elements, server_options, server_groups)) {
		printf("Return code: %d, Error: %s", OK, mysql_error(mysql));
		exit(OK);
}

Which returns:

$./bug39693
Return code: 1, Error: mysql_embedded: unknown option '--notoption'
[27 Sep 2008 16:19] Ian Monroe
Where does that 'mysql' variable come from in mysql_error(mysql)?

I understand how error reporting happens after initialization, that works fine. But I don't see how it works during the initial initialization. To me it appears that its not implemented at all.
[28 Sep 2008 14:53] Ian Monroe
We've done like you suggested and it actually does work; the parameter given to mysql_error can be null and it works as expected.

I suggest that http://dev.mysql.com/doc/refman/5.1/en/mysql-error.html explain the behavior when given a null pointer; its not very obvious that it would work.
[29 Sep 2008 15:10] Ian Monroe
Since writing that message I got a backtrace that seemed to show error_report returning nonsense. So I'm actually not sure if mysql_error( 0 ) has a defined behavior or not. Would be nice to know. :)
[2 Oct 2008 15:09] Paul DuBois
Sveta's example is incorrect because it passes a mysql structure to mysql_error(). But mysql_library_init() is the first API call, so at that point you have no mysql structure.

The mysql_error() function is documented as taking a mysql structure argument. This does not imply NULL should work, nor should NULL be passed.

mysql_library_init() merely returns non-zero when it fails. Providing additional information about the cause of failure could be useful, but that is more appropriately filed as feature request.
[2 Oct 2008 15:26] Ian Monroe
Ok thanks for the info.

mysql_error does work generally with a null parameter. But I guess I'll disable that from happening before we make a stable release.
[2 Oct 2008 17:20] Sveta Smirnova
Thank you for the feedback.

I don't understand why you say mysql_error shows nonsense:

$g++ -o bug39693 bug39693.cpp `/Users/apple/Applications/mysql-5.1/bin/mysql_config --include --libmysqld-libs` -g
/usr/bin/ld: warning multiple definitions of symbol ___cxa_pure_virtual
/Users/apple/Applications/mysql-5.1/lib/mysql/libmysqld.a(my_new.o) definition of ___cxa_pure_virtual in section (__TEXT,__text)
/usr/local/lib/gcc/i386-apple-darwin8.8.1/4.1.2/../../../libstdc++.dylib(single module) definition of ___cxa_pure_virtual

$./bug39693 
Return code: 1, Error: mysql_embedded: unknown option '--notoption'

$cat bug39693.cpp
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "mysql.h"

MYSQL *mysql;

int main() {
   static const int num_elements = 5;
    char **server_options = new char* [ num_elements + 1 ];
    server_options[0] = "amarokmysqld";
    server_options[1] = "--notoption";
    server_options[2] = "--asdfwer";
    server_options[3] = "--default-storage-engine=MYISAM";
    server_options[4] = "--skip-innodb";
    server_options[5] = 0;

    char **server_groups = new char* [ 3 ];
    server_groups[0] = "amarokserver";
    server_groups[1] = "amarokclient";
    server_groups[2] = 0;

    if (int OK = mysql_library_init(num_elements, server_options, server_groups)) {
                printf("Return code: %d, Error: %s", OK, mysql_error(mysql));
                exit(OK);
        }
    
        mysql = mysql_init(NULL);
}
[2 Oct 2008 17:25] Sveta Smirnova
See definition of mysql_error else:

const char * STDCALL mysql_error(MYSQL *mysql)
{
  return mysql ? mysql->net.last_error : mysql_server_last_error;
}

Else see definition of set_mysql_error where mysql_server_last_error is set:

void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate)
{
  NET *net;
  DBUG_ENTER("set_mysql_error");
  DBUG_PRINT("enter", ("error :%d '%s'", errcode, ER(errcode)));
  DBUG_ASSERT(mysql != 0);

  if (mysql)
  {
    net= &mysql->net;
    net->last_errno= errcode;
    strmov(net->last_error, ER(errcode));
    strmov(net->sqlstate, sqlstate);
  }
  else
  {
    mysql_server_last_errno= errcode;
    strmov(mysql_server_last_error, ER(errcode));
  }
  DBUG_VOID_RETURN;
}
[13 May 2012 18:30] MySQL Verification Team
on libmysqld in mysql-trunk (5.6.6) I get a useless error message.

# embedded mysql_library_init() failed (2000, mysql_embedded: Shutdown complete
)

The code is as follows (note the type in consolt):

static const char *server_options[]={"gemsbok", "--defaults-file=my.ini","--consolt", NULL };
int num_elements = (sizeof(server_options) / sizeof(char *)) - 1;
static const char *server_groups[] = { "libmysqld_server",NULL };
if(mysql_library_init(num_elements, (char**)server_options, (char**)server_groups))
{
  printf("# embedded mysql_library_init() failed (%d, %s)\n",mysql_errno(NULL),mysql_error(NULL));
  return 1;
}
[23 May 2012 18:40] MySQL Verification Team
i meant it's not fixed imho.  how am i to know what went wrong with such error message? 

"# embedded mysql_library_init() failed (2000, mysql_embedded: Shutdown complete)"

nothing written to the error log or stdout/stderr either.
[29 May 2012 19:11] Sveta Smirnova
Thank you for update.

Verified as described. After 5.5 it is even worse nonsense returned: "mysql_embedded: Shutdown complete"
[20 Jun 2012 0:47] Stefan Brüns
One problem is that the error message is overwritten by any subsequent error.

At least for the initialization of the error messages, there is a bug that is does not fail immediately, but sometime later. At this time, the error message is already overwritten.
[20 Jun 2012 0:49] Stefan Brüns
Patch: fail immediately when errmsg.sys can not be loaded

Attachment: mysql_fail_on_missing_errmsg_sys.patch (text/x-patch), 2.01 KiB.

[31 Oct 2014 17:54] MySQL Verification Team
I beg to differ this is a FR. Every time I am forced to step through in debugger to find out what is wrong. Hardly user friendly, or even dev friendly!