Wednesday, February 24, 2016

mysql_real_connect is not thread safe

The "mysql_real_connect" function is used by MySQL clients, including multi-threaded clients,  to connect to a MySQL server.  The "mysql_real_connect" function is allowed to be run by concurrent threads without application level serialization.  Unfortunately, the thread sanitizer found a data race in the "mysql_real_connect" function when processing the character set directory option.  This data race means that the "mysql_real_connect" function is not thread safe.   The data race occurs in the MySQL client connection code because  the character set directory option is stored in a global variable and is used without serialization by the client side connection code.  I suspect that the  character set directory option is not typically used by most MySQL clients.  However, since the option exists, it should work correctly.

Here are some details of the bug.  When MySQL 5.7.11 is built with the thread sanitizer enabled and the mysqlslap test is run, the thread sanitizer reports a data race in the client side connection software.  The data race occurs in the "mysql_set_character_set_with_default_collation" function, which is called when the client is executing the "mysql_real_connect" function. The data race occurs because the character set directory option to the "mysql_real_connect" function is temporarily stored in the "charset_dir" global variable so that it can be used by some other internal functions. Since there is no serialization on this global variable, the thread sanitizer reports a data race. The effect of this bug is that the character set directory for one thread can be used by another thread erroneously.

A possible bug fix could serialize the "mysql_set_characeter_set_with_default_collation" function since it is not thread safe. Alternatively, the charset directory could be passed as a function parameter rather than as a global variable to various internal functions.

The data race in the client side connection software can also be demonstrated when running a simplified mysqlslap test with helgrind.

The thread sanitizer and helgrind race detectors found a data race in the client side MySQL connection software.  These race detectors can be used to find data races in multi-thread software, like the client and server side MySQL software.  Unfortunately, these race detectors are not integrated into the MySQL software.  It would be nice to identify data races in the MySQL software before MySQL is running in production.  I created MySQL feature request #80409 to support the thread sanitizer in the MySQL software.

Versions:
MySQL 5.7.11, MySQL 5.6.29 and probably prior versions
clang 3.9
Ubuntu 15.10