这个问题花费了我几个小时的时间,真是很坑,根本原因是对功能缺少先从基本单元测试,再综合联调,太自信了,搞了一下午加上晚上几个小时。
一、问题现象
像题目说的,我在一个开源软件上进行更改代码,添加入mysql的功能,本来是简单的功能,写好之后一运行报错:Buffer type is not supported
.
报错代码的位置如下,就是if那一行代码。
if (mysql_stmt_bind_param(globalSpiderFlowDef.mysql_stmt[id], ppara))
{
SCLogError(SC_ERROR_MYSQL_BIND, "Mysql bind error reason:%s ||,%s \n",mysql_stmt_error(globalSpiderFlowDef.mysql_stmt[id]),mysql_error(&globalSpiderFlowDef.mydata[id]));
SCLogError(SC_ERROR_MYSQL_BIND,"tid:%d",gettid());
json_decref(object);
return SPIDER_FAILED;
}
二、问题探索
1、看到这个错误,我首先想到的是,这个bind变量ppara的类型难道不对?用日志输出了类型,发现是对的。
2、难道绑定变量的值有异常,导致的?所以我改了代码用了固定值,还是不行。
3、难道是mysql的服务器的版本和我客户端版本差异,所以我写个简单的例子,例子可以正常跑,代码就是死活不行。
4、简化代码,我只对表里面插入一条数据,绑定变量和参数赋值用和例子一样的代码,结果仍然报错。
5、难道是多线程引起的,特意对每个线程定义一个程序,通过调试线程的办法,去看下值有没有问题,结果也同样没发现问题。
1) ps -ef|grep xxx
查到进程ID 假设为pid
2)ps -T -p pid
根据pid 来获取线程号,同时还会打印线程名,非常有帮助。
3)查看线程的调用栈信息
pstack 线程id
查看到线程的调用栈,发现除了工作线程32个输出日志,还有统计线程,但是这里面没有找到详细信息。
4) 继续用gdb查看线程信息
gdb attach 主线程id
>info threads
#获取线程信息
>thread 36
#根据线程的id 对应,切换到这个线程id上面去。
>where
#打印线程栈信息,没有获得上面参考信息
5)为了将代码中的获取的线程id和ps -T看到的线程id一致,通过
#define gettid() syscall(SYS_gettid)
来获取tid、 并没有解决问题。
这时候我已经处于暴躁的边缘,这到底是什么鬼东西,我这时候想到开始编译的时候,我遇到一个找不到mysql的动态库错误。
库是: libmariadb.so.3
这个库是mysql的库,我又主动引用了mysql的libmysqlclient库,虽然最终程序连接这个库有点奇怪,不过并没有引起我的注意。
我随意地用ldd看下测试程序的连接库:
发现了这个奇怪的问题,就是测试程序并没有连这个动态链接库。
根据此,特意到configure.ac中主动屏蔽了这个库,结果还是会连接到这个库,而libmysqlclient并没有连接到。
三、根本原因
上面注意到了,正式代码和测试代码的连接库不一样,后面改动的几乎一样,那么是链接库不同造成的问题很大。
--with-libmysql-includes=/usr/local/mysql/include/mysql --with-libmysql-libraries=/usr/local/mysql/lib
开源软件上是通过这样方式指定连接库的。
而测试程序是通过如下方式指定链接库的.
-L/usr/lib/mysql -L/usr/lib64/mysql -L/usr/lib/mysql
按照测试环境路径重新configure ,编译运行,程序就这样奇迹般的好了。