Bug #91820 Connector C++ JDBC and mysqlclient crash due to destruction order of globals
Submitted: 27 Jul 2018 13:18 Modified: 20 Aug 2018 19:20
Reporter: Lefteris E Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / C++ Severity:S3 (Non-critical)
Version:8.0.12 OS:Windows
Assigned to: CPU Architecture:Any
Tags: C++, connector, crash, destruction, static

[27 Jul 2018 13:18] Lefteris E
Description:
When using the JDBC Connector C++ statically linked, when the program exits, the application crashes with "read access violation". 

client_plugin.cc line 363: p->plugin was 0xFFFFFFFFFFFFFFB7

Compiled with: static (lib), static runtime (MT), x64, Visual Studio 2017
using mysql client 8.0.11 and connector c++ 8.0.11

How to repeat:
There is no guarantee on the order of destruction of global variables across compilation modules. There is a case where the global variable of the client library is released before the global variable of the JDBC connector C++.

in mysql_driver.cpp the global variable:
struct st_client_plugin_int *plugin_list[MYSQL_CLIENT_MAX_PLUGINS];

in mysql_driver.cpp the global variable:
static std::map< sql::SQLString, boost::shared_ptr<MySQL_Driver> > driver;

If plugin_list is released before driver, then driver's destructor will attempt to access plugin_list which is no longer valid.

Suggested fix:
Need some way to guarantee that driver is destructed before plugin_list.
[30 Jul 2018 6:55] Lefteris E
The two files containing the globals are:
client_plugin.cc in Connector C++ JDBC
mysql_driver.cpp in MySql C connector
[30 Jul 2018 7:15] Lefteris E
Here is the sequence of destruction of the driver that leads to accessing the other global

mysql_driver.cpp line 74 (static std::map< sql::SQLString, boost::shared_ptr<MySQL_Driver> > driver;)
mysql_connection.h line 181 (boost::shared_ptr< NativeAPI::NativeConnectionWrapper > proxy;)
mysql_native_driver_wrapper.h line 51 (boost::shared_ptr<IMySQLCAPI> api;)
libmysql_static_proxy.cpp line 55  (this->library_end();)
libmysql_static_proxy.cpp line 252 (return ::mysql_library_end();)
libmysql.cc line 194 (mysql_client_plugin_deinit();)
client_plugin.cc line 362 (for (p = plugin_list[i]; p; p = p->next) )
[30 Jul 2018 7:29] Lefteris E
*small correction

mysql_driver.cpp line 74 (static std::map< sql::SQLString, boost::shared_ptr<MySQL_Driver> > driver;)
mysql_driver.h line 58 (boost::scoped_ptr< ::sql::mysql::NativeAPI::NativeDriverWrapper > proxy;)
mysql_native_driver_wrapper.h line 51 (boost::shared_ptr<IMySQLCAPI> api;)
libmysql_static_proxy.cpp line 55  (this->library_end();)
libmysql_static_proxy.cpp line 252 (return ::mysql_library_end();)
libmysql.cc line 194 (mysql_client_plugin_deinit();)
client_plugin.cc line 362 (for (p = plugin_list[i]; p; p = p->next) )

By following the destruction path of these scoped objects we land in client_plugin.cc which uses the plugin_list global. This is the global that was destroyed before the destructor of the driver global got a chance to use it.
[30 Jul 2018 22:23] Lefteris E
after closer investigation, the global variable in the mysql c library that is destructed and causes the access violation is:

static MEM_ROOT mem_root; (client_plugin.cc line 106)
[10 Aug 2018 8:17] Lefteris E
The problem persists in 8.0.12
[16 Aug 2018 9:55] Luis Silva
Patch trying to address problem

Attachment: 0001-Bug-91820-Fix-static-linking-destruction-order.patch (text/x-patch), 1.18 KiB.

[16 Aug 2018 9:57] Luis Silva
Hi Lefteris,

Can you please check if the supplied patch works?

Can't still reproduce this... in case the patch don't work, can you please provide the cmake options passed to build either server and connector?

Thanks!

Luís
[16 Aug 2018 9:59] Luis Silva
One thing I forgot... the patch has to be applied inside jdbc folder!

Thanks,
Luís
[16 Aug 2018 13:23] Lefteris E
I have tested the patch and yes, it solves the problem :)

I also checked C++ specification and I believe that the destruction order is now deterministic

https://github.com/cplusplus/draft/raw/master/papers/n4762.pdf
8.7 Declaration Statement (point 4)
6.8.3.4 Termination (point 3)
[20 Aug 2018 11:07] Rafal Somla
Posted by developer:
 
Also fixed in 1.1 code base: 3218edace61af38bdd6c3029d1cd5a04c3bfd1f4
[20 Aug 2018 19:20] Paul DuBois
Posted by developer:
 
Fixed in 8.0.13.

Applications that were statically linked to the legacy JDBC connector
could encounter a read access violation at exit time due to
nondeterministic global destruction order.