mysql - C++ thread attach/dettach segfaults -


i use plugin written in c++ running queries on mysql. it's used inside xojo (www.xojo.com) made application.

the problem if many queries executed crashes on linux segmentation fault.

the plugin works detaching calling thread before executing query in order not block main application etc , re-attaching once it's done. think re-attaching problem (gdb debugging in linux seems this) due not having symbols on xojo's framework i'm not sure.

this 2 methods/functions used detaching , re-attaching

void reattachcurrentthread(void *token) {     static void (*pattachthread)(void*) = nullptr;     if (!pattachthread)         pattachthread = (void (*)(void *)) gresolver("_unsafeattachcurrentthread");     if (pattachthread) pattachthread( token ); }  void * detachcurrentthread(void) {     static void * (*pdetachthread)(void) = nullptr;     if (!pdetachthread)         pdetachthread = (void * (*)(void)) gresolver("_unsafedetachcurrentthread");     if (pdetachthread) return pdetachthread();     return nullptr; } 

and here 1 place called:

realdbcursor mysqlperformselect(mysqldatabasedata *db, realstring querystr) {     if (db->fconnection == nullptr) return nullptr;      if (!lockdatabaseusage( db )) return nullptr;      realstringdata stringdata;     if (!realgetstringdata( querystr, realgetstringencoding( querystr ), &stringdata )) return nullptr;      void *detachtoken = detachcurrentthread();     int err = mysql_real_query( db->fconnection, (const char *)stringdata.data, stringdata.length );     reattachcurrentthread( detachtoken );     db->capturelasterror();      realdisposestringdata( &stringdata );      realdbcursor retcursor = nullptr;     if (0 == err) {         // allocate cursor         mysqlcursordata *curs = new mysqlcursordata;         bzero( curs, sizeof( mysqlcursordata ) );          curs->fcursor = new mysqlcursor( db );          retcursor = newdbcursor( curs );     }      unlockdatabaseusage( db );      return retcursor; } 

my question is: there wrong the code above , expected cause segfault because it's not being careful somehow etc? i'm not c++ programmer seems blunt in understanding, not trying see if thread available first etc. again, i'm not c++ programmer i'm saying may absurd etc...

the "whole" plugin's code here: plugin's source

there @ least 2 problems code:

  1. the calls reattachcurrentthread()/detachcurrentthread() not synchronized
  2. unlockdatabaseusage() not called: function mysqlperformselect() can return without calling unlockdatabaseusage()

the first problem can fixed follows:

#include <mutex>  std::mutex g_attachmentmutex; void reattachcurrentthread(void *token) {     std::lock_guard<std::mutex> mlg(g_attachmentmutex);     static void (*pattachthread)(void*) = nullptr;     if (!pattachthread)         pattachthread = (void (*)(void *)) gresolver("_unsafeattachcurrentthread");     if (pattachthread) pattachthread( token ); }  void * detachcurrentthread(void) {     std::lock_guard<std::mutex> mlg(g_attachmentmutex);     static void * (*pdetachthread)(void) = nullptr;     if (!pdetachthread)         pdetachthread = (void * (*)(void)) gresolver("_unsafedetachcurrentthread");     if (pdetachthread) return pdetachthread();     return nullptr; } 

the second problem can fixed follows:

class mysqlperformselectcleaner {     mysqldatabasedata *_db; public:     mysqlperformselectcleaner(mysqldatabasedata *db)         : _db(db)     {     }     ~mysqlperformselectcleaner()     {         unlockdatabaseusage(_db);     } }; realdbcursor mysqlperformselect(mysqldatabasedata *db, realstring querystr) {     if (db == nullptr || db->fconnection == nullptr) return nullptr;      if (!lockdatabaseusage( db )) return nullptr;     mysqlperformselectcleaner c(db);      realstringdata stringdata;     if (!realgetstringdata( querystr,          realgetstringencoding( querystr ), &stringdata ))      {         return nullptr;     }      void *detachtoken = detachcurrentthread();     // perhaps check detachtoken==nullptr needed here     int err = mysql_real_query( db->fconnection, (const char *)stringdata.data, stringdata.length );     reattachcurrentthread( detachtoken );     db->capturelasterror();      realdisposestringdata( &stringdata );      realdbcursor retcursor = nullptr;     if (0 == err) {         // allocate cursor         mysqlcursordata *curs = new mysqlcursordata;         bzero( curs, sizeof( mysqlcursordata ) );          curs->fcursor = new mysqlcursor( db );          retcursor = newdbcursor( curs );     }      // rely on cleaner call this: unlockdatabaseusage( db );     return retcursor; } 

Comments

Popular posts from this blog

How has firefox/gecko HTML+CSS rendering changed in version 38? -

javascript - Complex json ng-repeat -

jquery - Cloning of rows and columns from the old table into the new with colSpan and rowSpan -