August 2010 Archives

使用Mysql出core

  • 问题描述

在主线程内初始化mysql,在子线程内调用mysql_real_connect,导致coredump

  • 问题简化重现
20 #include <mysql/mysql.h>
21 #include <pthread.h>
22 void* func(void* arg)
23 {
24 MYSQL* mysql = (MYSQL *)arg;
26 mysql_real_connect(mysql, "127.0.0.1″, "root", "213456″, "FC_word", 3344, NULL, 0);
27 mysql_close(mysql);
29 return (void *)0;
30 }
31
32 int main()
33 {
34 MYSQL mysql;
35 if (NULL == mysql_init(&mysql)){
36 return -1;
37 }
38 pthread_t thread;
39 pthread_create(&thread, NULL, func, &mysql);
40 pthread_join(thread, NULL);
41
42 return 0;
43 }

会core掉:

#0 0×0000000000417db2 in my_stat ()
(gdb) bt
#0 0×0000000000417db2 in my_stat ()
#1 0×00000000004169f4 in my_read_charset_file ()
#2 0×0000000000416cb2 in init_available_charsets ()
#3 0×00000000004170ea in get_charset_by_csname ()
#4 0×0000000000405fda in mysql_init_character_set ()
#5 0×0000000000407024 in mysql_real_connect ()

  • 问题原因

粗略看了下源代码,Mysql_init()会初始化一些线程私有数据。 Mysql_init()中调用my_thread_init(), 其中设置线程私有数据。

  • 解决办法

所以可以这么使用:(1)mysql_init()和mysql_real_connect()放在一起:
(2)调用mysql_thread_init()和mysql_thread_end()来初始化和线程相关的数据
如:

22 void* func(void* arg)
23 {
24 MYSQL* mysql = (MYSQL *)arg;
25 mysql_thread_init();
26 mysql_real_connect(mysql, "127.0.0.1″, "root", "213456″, "FC_word", 3344, NULL, 0);
27 mysql_close(mysql);
28 mysql_thread_end();
29 return (void *)0;
30 }

  • 其他

另外还遇到一个比较诡异的问题,MYSQL_OPT_RECONNECT不起作用。具体情况是:
Mysql server 使用5.0.22版本, mysql client api 使用third-64/mysql下的5.1.30版本, 重连不起作用,mysql_error也被置空
Mysql server 使用5.0.45版本(凤巢线上版本), mysql client api 使用third-64/mysql下的5.1.30版本, 重连起作用了。
提醒大家使用时注意mysql sever 和client api的版本,^_^

  • 其他共享经验

mysql_init()不是完全线程安全的,但是只要成功调用一次就后就线程安全了,如果有多线程并发使用mysql_init(),建议在程序初始化时空调一次mysql_init(),他的这点特性很像qsort() 。

autoconf讲座一篇

强大的autoconf,分享一下
autoconf.ppt

使用rcsid来控制你的库版本

RCS是CVS的前身,详情可见GNU网站 http://www.gnu.org/software/rcs/。RCS版本控制系统的Magic Keywords这一节中说明了rcsid的用法。
在BSD的代码中,一般读者都会发现在很多地方都会出现static char rcsid[] = “$FreeBSD … $”这样的字符串。
通常在BSD的代码中,前几行会有和rcsid字符串差不多的注释字符。和rcsid字符串一样,这些字串都是由CVS自动生成更新的,主要用来保存文件最后更改的时间、作者等信息。在文件首行加个注释很好理解,而将其放在字符串中则是为了在将文件编译为二进制文件之后依然可以保留这些信息。虽然现在BSD的代码都是用CVS管理了,但还是可以看到rcsid这东东。
现实的工程当中,当编译库文件的时候,我们发现系统下的文件已经变得不是很干净,到处是依赖的动态或者静态库的文件,那么,受污染的系统怎么保证编译的可执行文件或者库文件是正确的版本呢?这里rcsid就显得十分重要了。
一般创建个rcsid专有的宏文件rcsid.h,定义如下:

#if defined(NO_RCSID) || defined(lint)
#define RCSID(x) /* empty */
#elif __STDC__
/*
* This function is never called from anywhere, but it calls itself
* recursively only to fool gcc to not generate warnings :-).
*/
static const char *rcsid(const char *);
#define RCSID(x) static const char *rcsid(const char *s) { return rcsid(x); }
#else
#define RCSID(x) static char *rcsid(s) char *s; { return rcsid(x); }
#endif
然后在.cpp文件中引用这个头文件后,只要加入一行
RCSID("$Version: your version information $");
或使用:
static const char rcsid[] = "$Id: " __FILE__ ",v 1.0.0-0 " __DATE__ " " __TIME__ " Cnangel Exp $";
编译成二进制或库后,我们可以使用:
ident <二进制文件或库>
来检测二进制或库是否包含“your version information”的字样,从而确定你的二进制或库文件是正确的。
当然,这种方式也可以直接使用到Linux系统上哟。
在NetBSD中还可以看到__COPYRIGHT,它也有类似的作用,用what可以查看这个字符串。

[转贴]周报的逻辑

最近新同事加入很多,按照我的要求,入职半年内需要发送周报给我,半年后自己选择是否仍需发送。这里有个看起来很愚蠢的问题。
 
为什么要发周报?

Monthly Archives

Pages

Powered by Movable Type 7.7.2

About this Archive

This page is an archive of entries from August 2010 listed from newest to oldest.

July 2010 is the previous archive.

September 2010 is the next archive.

Find recent content on the main index or look in the archives to find all content.