Hi there I'm having trouble in a multi-threaded client with segfaults in mysql_free_result(). After trawling the archives, I've found other people reporting the same problem, but the fix in each case has been to make sure that the pointer returned from mysql_store_result() is non-null. This is not useful in my case, unfortunately, because I've done that. I humbly request the assistance of the gathered ladies and gentlemen. - Running on FreeBSD 4.3-STABLE. - The library was compiled --without-server --enable-thread-safe-client, and because my own code is compiled with -pthread, I've changed libtool to cause libmysqlclient_r to be linked to libc_r. (Removes the ugly compile-time warnings.) - The client has a separate connection for each thread. If anybody is able to suggest where I'm going wrong, I'd be most grateful. allen ######################## A sample backtrace from gdb: Program received signal SIGSEGV, Segmentation fault. 0x481496fd in _thread_leave_cancellation_point () from /usr/lib/libc_r.so.4 (gdb) backtrace #0 0x481496fd in _thread_leave_cancellation_point () from /usr/lib/libc_r.so.4 #1 0x48149b41 in free () from /usr/lib/libc_r.so.4 #2 0x480a0d23 in my_no_flags_free () from /usr/home/allen/mysql//lib/mysql/libmysqlclient_r.so.10 #3 0x480a38bc in free_root () from /usr/home/allen/mysql//lib/mysql/libmysqlclient_r.so.10 #4 0x4809ad5d in free_rows (cur=0x8090380) at libmysql.c:414 #5 0x4809b4bf in mysql_free_result (result=0x811f580) at libmysql.c:661 #6 0x80599ab in adm_cleanup (result=0x811f580) at admlayer.c:3115 #7 0x8050607 in do_setstatus (m=0xbfadcf84, mcon=0xbfadcd54, r=0xbfadcf60) at messagehandling.c:2257 #8 0x8049990 in comms_handler (thing=0x8082000) at comms.c:230 #9 0x480d7ab3 in _thread_start () from /usr/lib/libc_r.so.4 #10 0x0 in ?? () ######################## The equivalent situation recorded in the mysql log (options: d:t:O,./trace/mysql.trace ) (excerpt) >mysql_real_query | enter: handle: bfadcd54 | query: Query = "UPDATE users SET status = '11' WHERE userid = '1'" | >net_flush | | >net_real_write | | <net_real_write | <net_flush <mysql_real_query >mysql_read_query_result | >free_old_query | <free_old_query <mysql_read_query_result >mysql_real_query | enter: handle: bfadcd54 | query: Query = "UPDATE contact SET changed = 1 WHERE child_id = '1'" | >net_flush | | >net_real_write | | <net_real_write | <net_flush <mysql_real_query >mysql_read_query_result | >free_old_query | <free_old_query <mysql_read_query_result >mysql_real_query | enter: handle: bfadcd54 | query: Query = "SELECT parent_id FROM contact WHERE child_id = '1'" | >net_flush | | >net_real_write | | <net_real_write | <net_flush <mysql_real_query >mysql_read_query_result | >free_old_query | <free_old_query | >read_rows | | exit: Got 1 rows | <read_rows | >unpack_fields | <unpack_fields <mysql_read_query_result >mysql_store_result | >read_rows | | exit: Got 2 rows | <read_rows <mysql_store_result >mysql_fetch_row <mysql_fetch_row >mysql_fetch_row <mysql_fetch_row >mysql_fetch_row | info: end of data <mysql_fetch_row >mysql_free_result | enter: mysql_res: 811f580 # file stops here ######################## The code that created the above traces (left out adm_retrievecontact() because all it does is call mysql_fetch_row() until running out of rows; has no bearing on the situation as far as I can see): int do_setstatus( struct message *m, MYSQL *mcon, struct response *r ) { unsigned int id; char query[QUERYLENGTH]; struct setstatus *a = (struct setstatus *)m->attr; void *result; r->key = get_user_key( m->userid ); r->userid = m->userid; if (! user_logged_in( m->userid )) { return make_naksetstatus( IM_ERR_LGGDOUT, r->buffer ); } if (a->newstatus == 0) { return make_naksetstatus( IM_ERR_MSGATTR, r->buffer ); } result = adm_setstatus( mcon, m->userid, a->newstatus, 1 ); if (! result) { return make_naksetstatus( IM_ERR_SRVRERR, r->buffer ); } while (adm_retrievecontact( result, &id ) == ADM_MORE_ROWS) { record_contact( id ); } adm_cleanup( result ); return make_acksetstatus( r->buffer ); } ### int adm_cleanup( void *result ) { mysql_free_result( (MYSQL_RES *)result ); return 0; } ### void *adm_setstatus( MYSQL *mcon, unsigned int userid, short newstatus, short count ) { int i; char query[QUERYLENGTH]; MYSQL_RES *res; if (count > ADM_MAXRECURS) { return NULL; } sprintf( query, "UPDATE users SET status = '%d' WHERE userid = '%u'", newstatus, userid ); mysql_query( mcon, query ); i = mysql_errno( mcon ); switch (i) { case CR_SERVER_GONE_ERROR: /* reconnect (recurse) */ case CR_SERVER_LOST: /* recurse, try again */ return adm_setstatus( mcon, userid, newstatus, count + 1 ); break; case 0: /* success */ break; default: /* fail */ { char logentry[LOGENTLEN]; sprintf( logentry, "MySQL error %d: %s", i, mysql_error( mcon ) ); write_to_log( logentry ); } return NULL; break; } sprintf( query, "UPDATE contact SET changed = 1 WHERE child_id = '%u'", userid ); mysql_query( mcon, query ); i = mysql_errno( mcon ); switch (i) { case CR_SERVER_GONE_ERROR: /* reconnect (recurse) */ case CR_SERVER_LOST: /* recurse, try again */ return adm_setstatus( mcon, userid, newstatus, count + 1 ); break; case 0: /* success */ break; default: /* fail */ { char logentry[LOGENTLEN]; sprintf( logentry, "MySQL error %d: %s", i, mysql_error( mcon ) ); write_to_log( logentry ); } return NULL; break; } sprintf( query, "SELECT parent_id FROM contact WHERE child_id = '%u'", userid ); mysql_query( mcon, query ); i = mysql_errno( mcon ); switch (i) { case CR_SERVER_GONE_ERROR: /* reconnect (recurse) */ case CR_SERVER_LOST: /* recurse, try again */ return adm_setstatus( mcon, userid, newstatus, count + 1 ); break; case 0: /* success */ break; default: /* fail */ { char logentry[LOGENTLEN]; sprintf( logentry, "MySQL error %d: %s", i, mysql_error( mcon ) ); write_to_log( logentry ); } return NULL; break; } res = mysql_store_result( mcon ); return (void *)res; } -- Allen Grace Dark Blue Sea Pty Ltd ph +61 7 3007 0000 fax +61 7 3007 0001 ***The opinions expressed in this email are my own and are not representative of DBS Pty Ltd.*** --------------------------------------------------------------------- Before posting, please check: http://www.mysql.com/manual.php (the manual) http://lists.mysql.com/ (the list archive) To request this thread, e-mail <[EMAIL PROTECTED]> To unsubscribe, e-mail <mysql-unsubscribe-##L=##[EMAIL PROTECTED]> Trouble unsubscribing? Try: http://lists.mysql.com/php/unsubscribe.php