| Bug #115710 | Access violation writing location 0x0000000000000320 while opening connection | ||
|---|---|---|---|
| Submitted: | 29 Jul 2024 5:30 | Modified: | 12 Aug 2024 19:29 |
| Reporter: | Hennadii Niemtsov | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | Connector / ODBC | Severity: | S3 (Non-critical) |
| Version: | 9.0.0.0 | OS: | Windows (Windows 10 Enterprise Version:10.0.19045) |
| Assigned to: | CPU Architecture: | Other (AMD64) | |
| Tags: | access violation | ||
[29 Jul 2024 5:53]
Hennadii Niemtsov
VS2022 C++ project file to reproduce issue
Attachment: TestMySqlOdbc.zip (application/x-zip-compressed, text), 4.88 KiB.
[29 Jul 2024 5:55]
Hennadii Niemtsov
generated dump file
Attachment: TestMySqlOdbc_DMP.zip (application/x-zip-compressed, text), 15.16 MiB.
[30 Jul 2024 4:22]
MySQL Verification Team
Hello Hennadii Niemtsov, Thank you for the bug report. Verified as described. Regards, Ashwini Patil
[2 Aug 2024 4:02]
Hennadii Niemtsov
I found conditions when mysql_init() returns null. Here is explanation a little verbally so check attached PNG image for clarity. Here is what i found: Initially variables: mysql_client_init and my_thread_global_init_done are set to FALSE. Both threads are executing `mysql_server_init()`, but the first thread is the one that checks the state of `mysql_client_init` and changes it from `FALSE` to `TRUE`. As a result, the second thread follows a different execution path. If the second thread reads the `my_thread_global_init_done` variable before the first thread has set it to `TRUE`, the second thread will return a null pointer from `mysql_init()`.
[2 Aug 2024 4:03]
Hennadii Niemtsov
when mysql_init() returns null
Attachment: nullptr.png (image/png, text), 38.78 KiB.
[12 Aug 2024 9:41]
Bogdan Degtyariov
Posted by developer: The issue happened because of concurrent calls to mysql_init() that called mysql_library_init() simultaneously. It was not thread safe The patch makes sure mysql_library_init() is called before any mysql_init() calls. This makes mysql_init() thread safe. Changes are pushed in the source tree.
[12 Aug 2024 19:29]
Philip Olson
Posted by developer: Fixed as of the upcoming MySQL Connector/ODBC 9.1.0 release, and here's the proposed changelog entry from the documentation team: The internal mysql_init() method used for making connections is now thread safe. Thank you for the bug report.

Description: In my C++ test console application running in VS2022 in Debug mode there are 2 threads which is trying to establish a connection to MySQL server (v8.0.38) DB running on the same laptop. The connection is made via preconfigured System DSN using ODBC Data source (64 bit) Admin tool with chosen MySql ODBC 9.0 ANSI Driver and TCP connection via 3306 port with password authentication. Occasionally it throws an exception: Exception thrown at 0x00007FFC426FE6F8 (libmysql.dll) in TestMySqlOdbc.exe: 0xC0000005: Access violation writing location 0x0000000000000320. Here is stack trace for 1 of 2 thread where exception is thrown: Not Flagged > 6156 0 Worker Thread ucrtbased.dll thread libmysql.dll!00007ffc42c4e6f8 libmysql.dll!00007ffc42c4e6f8() myodbc9a.dll!DBC::connect(DataSource * dsrc) Line 341 myodbc9a.dll!MySQLConnect() Line 1112 myodbc9a.dll!SQLConnect() Line 172 odbc32.dll!00007ffd1ff04ea3() odbc32.dll!00007ffd1feeaa2b() odbc32.dll!00007ffd1feea627() odbc32.dll!00007ffd1ff1e14f() TestMySqlOdbc.exe!run(int i) Line 89 TestMySqlOdbc.exe!main::__l2::<lambda_2>::operator()() Line 120 TestMySqlOdbc.exe!std::invoke<`main'::`2'::<lambda_2>>(main::__l2::<lambda_2> && _Obj) Line 1705 TestMySqlOdbc.exe!std::thread::_Invoke<std::tuple<`main'::`2'::<lambda_2>>,0>(void * _RawVals) Line 60 ucrtbased.dll!00007ffc5abc3010() kernel32.dll!00007ffd4d297374() ntdll.dll!00007ffd4ec5cc91() For more details the generated dmp file is attached. Exception happens in connector.cc module in SQLRETURN DBC::connect(DataSource *dsrc) method. it seems that mysql object is not initialized and points to NULL after line #318: mysql = mysql_init(nullptr); Specification says that return NULL is possible in case of insufficient memory. Windows Task Manager shows that on my laptop it is about 86% of 16 Gb RAM in use. Next lines of code without check for NULL it is trying to set the connection option calling mysql_options() with no valid mysql connection handler passed in 1st parameter. How to repeat: - Create a database in the local instance of MySQL - Create a DSN, in the ODBC Administration console (64 bit), using MySQL Connector 9.0 ANSI and pointing to the created database. - Open attached C++ console project in VS2022 and run few times until get the exception (for me it happens in 1 of 10 times). Suggested fix: Please check the mysql connection handler for validity before calling any of mysql_options(). In case if mysql_init() returns null then set sql error and return from connect method like this: if (!mysql) return set_error("HY001", "Failed to initialize mysql", 0);