Bug #3434 MySQL-functions are causing "Bus error".
Submitted: 10 Apr 2004 8:12 Modified: 15 Feb 2005 14:22
Reporter: Christian Mörck Email Updates:
Status: Can't repeat Impact on me:
None 
Category:MySQL Server Severity:S2 (Serious)
Version: OS:MacOS (Mac OS X)
Assigned to: Jani Tolonen CPU Architecture:Any

[10 Apr 2004 8:12] Christian Mörck
Description:
First of all, i have never notice this error in any linux OS.

When i declare a "MYSQL*" to hold the returnvalue from any mysql-function and the mysql-function 
returns an error, an "Bus error" will accure while running the program. This won't accure if i don't 
declare a "MYSQL*" to hold the returnvalue or if the functions doesnt return an error. I noticed this 
when i loaded my program into another computer, not running the same mysql-databases as the last.

Below is an example from when it works and when it doesnt work. The code is in c/c++. Notice that 
"..." in an function-call has only been put there because this doesnt have with the problem to do.

-- This doesnt work if mysql_real_connect() returns an error.
MYSQL* conn;
if( (conn = mysql_real_coonnect(...)) == NULL)
    perror("mysql-error");

-- This works just fine.
MYSQL *conn;
if(mysql_real_connect(...) == NULL)
  perror("mysql-error");

Notice that i only know that this accure in Mac OS X Panther and that it only accures when the 
databases that i try to connect to doesnt exist. If this accure when some other error accure, i do not 
have the knowledge about.

Of the record, i used the program "fink" to install mysql on this computer. What i know, fink only 
downloads the files and installs them. Fink should not be able to make this, but i can't say that it 
wouldnt.

How to repeat:
Mail me on christian@nordichardware.com. I would be very glad to know what the real problem is here.

Suggested fix:
A "Bus error" accure when a program tries to access memory that doesnt exist or havent been 
initialized. The problem probably exist inside your source code, which i don't have access to.
[6 May 2004 22:00] Jani Tolonen
First answer to your comment not having access to our source code;

mysql_real_connect() can be found from libmysql/libmysql.c source file,
in MySQL source distribution. All MySQL software is Open Source, so everybody
has basically access to everything. With the only exception being InnoDB hotbackup tool.

Second, can you please give an exact example of the C API code that you
are using? If you could make a small program that reproduces the problem,
that would be great. Even if it does not reproduce the problem on all
platforms, it would be helpful to see the whole of it.
[11 May 2004 0:02] Alexander Wirthmüller
Hi!

I encountered the same problem on MacOSX 10.3.3 (German) ; I'm running MySQL 4.0.18 (binary 
distribution)

My source code would be as simple as

GmDbConn::GmDbConn(const char* dbHost, const char* dbName, const char* dbUser, const char* 
dbPass) {
	mysql_init(gmDb);
	
	mysql_options(gmDb, MYSQL_OPT_CONNECT_TIMEOUT, "2");
	
	if (!mysql_real_connect(gmDb, dbHost, dbName, dbPass, dbUser, 0, NULL, 0)) {
		cout << "Connected to GainMaster database on " << dbHost << endl;
	} else {
		cout << "Failed to connect to database: " << mysql_error(gmDb) << endl;
	};
};

gdb says the bus error appears in cmath (which is not really informative, actually)

Greets
Alex
[11 May 2004 11:49] Alexander Wirthmüller
Hi again!

I solved the problem by using a reference for the database as proposed in all mySQL C API examples.

class GmDbConn {
public:
	MYSQL gmDb;

	GmDbConn(const char* dbHost, const char* dbName, const char* dbUser, const char* dbPass);
	~GmDbConn();
};

GmDbConn::GmDbConn(const char* dbHost, const char* dbName, const char* dbUser, const char* 
dbPass) {
	mysql_init(&gmDb);
	
	mysql_options(&gmDb, MYSQL_READ_DEFAULT_GROUP, "GainMaster");
	
	if (mysql_real_connect(&gmDb, dbHost, dbName, dbPass, dbUser, 0, NULL, 0)) {
		cout << "Connected to GainMaster database on " << dbHost << endl;
	} else {
		cout << "Failed to connect to database: " << mysql_error(&gmDb) << endl;
	};
};
[11 May 2004 20:18] Christian Mörck
To: Jani Tolonen

The code i gave was an example of what i'm using in a program. 

In my case the bug appeared because there wasnt any database of the name that i wanted to use. The problem was fixed very easy, but still mysql should return an error, and not let the kernel return a bus error.
[15 Feb 2005 14:22] Jani Tolonen
I have tried to repeat this bug on Mac OS 10.3.7, but without success.

I'm including the test that I tried in this answer. If someone can repeat the wrong
bus error using it as basis, or by providing a full test case, that would be good.

Please note that bus error may occur if the MYSQL variable is 'wrong' and is
passed to mysql_real_connect. Such can be a NULL argument, or a wrong pointer.
It may be possible to get bus error also, if the program is compiled with include files
from one version and linked with libraries from another version.

From the examples you provided I cannot see what the arguments to
mysql_real_connect() contained when the bus error was hit. A stack trace
with full source code of an example program might have revealed the problem.

Some background about mysql_real_connect() implementation; basically the function
expects that the MYSQL connection variable is fine. There are no tests for NULL argument,
nor checks for possible errors in the size of the variable and so on. It would be very hard
to catch all possible error situations, and trying so would result in a slower code. In this
case speed was preferred over checking many error cases, which normally should not
occur at all.

How to repeat:

Using 4.0.23 source.
Created a file client/test.c under the source tree. The source file and compilation
lines follow.

test.c is as follows:

#include "client_priv.h"

int main(int argc, char *argv[])
{
  MYSQL mysql;
  const char *dbhost="localhost", *dbname="notfound", *dbpass="", *dbuser="";

  mysql_init(&mysql);
  mysql_options(&mysql, MYSQL_OPT_CONNECT_TIMEOUT, "2");

  if (!(mysql_real_connect(&mysql, dbhost, dbuser, dbpass, dbname, 0, NULL, 0)))
  {
    fprintf(stderr, "Failed!\n");
    return -1;
  }
  else
  {
    fprintf(stderr, "Succeeded!\n");
  }
  return 0;
}

Compiled as follows:

gcc -DUNDEF_THREADS_HACK -I. -I. -I.. -I./../include -I../include -I./.. -I.. -I..     -g -O -DDBUG_ON -DSAFE_MUTEX    -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DIGNORE_SIGHUP_SIGQUIT -c `test -f 'test.c' || echo './'`test.c
/bin/sh ../libtool --preserve-dup-deps --mode=link gcc  -g -O -DDBUG_ON -DSAFE_MUTEX    -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DIGNORE_SIGHUP_SIGQUIT   -o test  test.o ../libmysql/libmysqlclient.la -lz -lm
gcc -g -O -DDBUG_ON -DSAFE_MUTEX -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DIGNORE_SIGHUP_SIGQUIT -o .libs/test test.o  ../libmysql/.libs/libmysqlclient.12.0.0.dylib -lz -lm

Alas this does not fail in bus error even if the database name is non-existing.
I tried repeating against the server that was compiled from the same source.
If one uses empty dbname or dbname that exists, the program prints 'succeeded',
otherwise 'failed'.
[15 Jul 2007 13:32] Vincent David
Hi,

I can report, that this bug remains unsolved on MacOsX Tiger (10.4.10). Is anyone actually taking care of or is MacOs too fa of scope to be worth it? The last named proposal works for me but it cost me almost a days work! 

Vincent
[16 Jul 2007 12:53] Hartmut Holzgraefe
Previous comment refers to Bug #29819 which was 
identified as user error due to use of unallocated
memory.