最近在写一个DBEngine,其内部封装了mysql的一些api操作,在写测试用例时发现如果包含多个测试用例组(TestSuite),会在执行第二个测试用例时在Mutex::Lock::Lock(mysql-connector-c-path\extra\yassl\src\lock.cpp, 47)处抛出异常,且this指针为nullptr。堆栈如下:1
2
3
4
5
6
7
8
9
10
11
12 	ntdll.dll!00007ffd35b7b40d()	Unknown
>	libmysql_d.dll!yaSSL::Mutex::Lock::Lock(yaSSL::Mutex & lm) Line 47	C++
 	libmysql_d.dll!yaSSL::Sessions::lookup(const unsigned char * id, yaSSL::SSL_SESSION * copy) Line 1829	C++
 	libmysql_d.dll!yaSSL_get_session(yaSSL::SSL * ssl) Line 513	C++
 	libmysql_d.dll!ssl_do(st_VioSSLFd * ptr, st_vio * vio, long timeout, int(*)(SSL *) func, unsigned long * ssl_errno_holder) Line 402	C
 	libmysql_d.dll!sslconnect(st_VioSSLFd * ptr, st_vio * vio, long timeout, unsigned long * ssl_errno_holder) Line 502	C
 	libmysql_d.dll!cli_establish_ssl(st_mysql * mysql) Line 3591	C
 	libmysql_d.dll!mysql_real_connect(st_mysql * mysql, const char * host, const char * user, const char * passwd, const char * db, unsigned int port, const char * unix_socket, unsigned long client_flag) Line 4774	C
 	DBEngine.dll!CMysqlConn::Connect() Line 41	C++
 	DBEngine.dll!CGeneralQueryTask::OnExecute(dbengine::IDBPool * pDBPool) Line 43	C++
 	DBEngine.dll!CDBThread::OnThreadRun() Line 35	C++
 	DBEngine.dll!CThreadBase::StartThread::__l2::<lambda>() Line 20	C++
回到yaSSL_get_session这一帧,可以确定是GetSessions()返回了空指针。查看GetSessions代码,以及结合yassl_pthread_once宏定义可以发现,c_session_initialize函数在整个运行时只执行了一次,执行标识由session_created记录,其最终调用Session_initialize为sessionsInstance生成一个对象,sessionsInstance在yaSSL_CleanUp函数内释放。
问题在于session_created标识没有随着sessionsInstance释放而重置,导致下一次执行到GetSessions时不会再重新生成Sessions对象。解决办法是在yaSSL_CleanUp函数内增加session_created重置操作。如下代码:1
2
3
4
5
6
7
8
9
10
11
12
13extern "C" void yaSSL_CleanUp()
{
    TaoCrypt::CleanUp();
    yaSSL::ysDelete(yaSSL::sslFactoryInstance);
    yaSSL::ysDelete(yaSSL::sessionsInstance);
    yaSSL::ysDelete(yaSSL::errorsInstance);
    // In case user calls more than once, prevent seg fault
    yaSSL::sslFactoryInstance = 0;
    yaSSL::sessionsInstance = 0;
    yaSSL::errorsInstance = 0;
    yaSSL::session_created = YASSL_PTHREAD_ONCE_INIT;
}