2012-07-03 43 views
1

我正在Linux平台上构建一个C应用程序。我需要使用libmysqlclient来连接数据库。在多线程应用程序中使用libmysqlclient

我下载的linux源代码包mysql-connector-c-6.0.2.tar.gz。我按照说明编译它。我得到了以下库:

libmysqlclient.a  libmysqlclient.so libmysql.so.16 
libmysqlclient_r.so libmysql.so  libmysql.so.16.0.0 

如果我的应用程序是多线程的,我可以联系我的libmysqlclient.a应用程序?根据mysql文档(http://forge.mysql.com/wiki/Autotools_to_CMake_Transition_Guide),使用cmake工具,客户端始终是线程安全的。

我的应用程序与libmysqlclient.a链接之后,我在下面的调用堆栈的应用得到一个崩溃:

#0 0x0867878a in my_stat() 
No symbol table info available. 
#1 0x08671611 in init_available_charsets.clone.0() 
No symbol table info available. 
#2 0x086720d5 in get_charset_by_csname() 
No symbol table info available. 
#3 0x086522af in mysql_init_character_set() 
No symbol table info available. 
#4 0x0865266d in mysql_real_connect() 

在我的申请,我有下面的代码在线程函数:

if (NULL == (pMySQL = mysql_init(NULL))) 
{ 
    return -1; 
} 

if (NULL == mysql_real_connect(pMySQL, ServerName, UserName, Password, Name, Port, NULL, 0)) 
{ 
    mysql_close(pMySQL); 
    return -1; 
} 

if (0 != mysql_query(pMySQL, pQuery)) 
{ 
    mysql_close(pMySQL); 
    return -1; 
} 

mysql_close(pMySQL); 

我没有使用libmysqlclient_r.so,因为我想静态链接到mysql客户端库。有没有办法用cmake生成libmysqlclient_r.a?

更新:

没有别人做什么,我只是改变MySQL客户端生成类型调试。现在我得到了mysql_init()函数中的崩溃。

在应用程序控制台,我得到下面的打印:

safe_mutex: Trying to lock unitialized mutex at /install/mysqlconnc/mysql-connector-c-6.0.2/mysys/safemalloc.c, line 520 

崩溃的调用堆栈如下:

#0 0x00556430 in __kernel_vsyscall() 
No symbol table info available. 
#1 0x45fdf2f1 in raise() from /lib/libc.so.6 
No symbol table info available. 
#2 0x45fe0d5e in abort() from /lib/libc.so.6 
No symbol table info available. 
#3 0x086833e5 in safe_mutex_lock (mp=0x915e8e0, my_flags=0, 
    file=0x895b9d8 "/install/mysqlconnc/mysql-connector-c-6.0.2/mysys/safemalloc.c", line=520) 
    at /install/mysqlconnc/mysql-connector-c-6.0.2/mysys/thr_mutex.c:178 
     error = 140915306 
     __PRETTY_FUNCTION__ = "safe_mutex_lock" 
#4 0x08682715 in _sanity ( 
    filename=0x895a87c "/install/mysqlconnc/mysql-connector-c-6.0.2/mysys/my_error.c", lineno=195) 
    at /install/mysqlconnc/mysql-connector-c-6.0.2/mysys/safemalloc.c:520 
     irem = 0xf2300468 
     flag = 0 
     count = 0 
#5 0x0868186b in _mymalloc (size=16, 
    filename=0x895a87c "/install/mysqlconnc/mysql-connector-c-6.0.2/mysys/my_error.c", lineno=195, MyFlags=16) 
    at /install/mysqlconnc/mysql-connector-c-6.0.2/mysys/safemalloc.c:130 
     irem = 0x0 
     data = 0x0 
     _db_stack_frame_ = {func = 0x6d617266 <Address 0x6d617266 out of bounds>, file = 0x65685f65 <Address 0x65685f65 out of bounds>, 
      level = 0, prev = 0x0} 
#6 0x0867e0e1 in my_error_register (errmsgs=0x89a7760, first=2000, last=2058) 
    at /install/mysqlconnc/mysql-connector-c-6.0.2/mysys/my_error.c:194 
     meh_p = 0x46087568 
     search_meh_pp = 0x1000 
#7 0x08655f7e in init_client_errs() 
    at /install/mysqlconnc/mysql-connector-c-6.0.2/libmysql/errmsg.c:238 
No locals. 
#8 0x08655fe3 in mysql_server_init (argc=0, argv=0x0, groups=0x0) 
    at /install/mysqlconnc/mysql-connector-c-6.0.2/libmysql/libmysql.c:128 
     result = 0 
#9 0x08651fc0 in mysql_init (mysql=0x0) 
    at /install/mysqlconnc/mysql-connector-c-6.0.2/libmysql/client.c:1606 

解决方案:

我把电话在创建线程之前将其添加到mysql_library_init(),并在线程终止之后调用mysql_library_end()。在每个线程中,我在线程函数的开始处调用了mysql_thread_init(),并在线程函数的末尾调用了mysql_thread_end()。这解决了崩溃的问题。

回答

2

更新

看来你需要调用mysql_library_init()mysql_init()

必须要么调用mysql_library_init() 产卵任何线程,或者使用一个互斥量,以保护之前无论您是调用mysql_library_init()还是通过 mysql_init()间接调用 调用。在任何其他客户端库调用之前执行此操作。

关于你原来的问题,libmysqlclient_r.so实际上是一个符号链接libmysql.so。你可以改变libmysql/CMakeLists.txt通过,而不是从下面的行取出SHARED关键字来产生一个静态库(libmysql.a):

ADD_LIBRARY(libmysql   SHARED ${CLIENT_SOURCES} libmysql.def) 

不过,我会建议(1)试图运行相同的代码,而无需使用线程,看看是否问题仍然存在,(2)构建和使用库的调试版本:

cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug 
make 

这样您可以更详细地调查问题。

+0

感谢你们提供了一个答案。请参阅我在上面的问题中添加的更新。 – geekowl

+0

@geekowl:考虑到您提供的其他信息,更新了答案。 – vitaut

+0

你说得对。我把电话给mysql_library_init()创建线程之前和解决崩溃的问题。感谢您提出宝贵的建议。他们帮助我解决了一个大问题。 – geekowl