[CONC-129] Bug in Async flow Created: 2015-06-09 Updated: 2015-09-08 Resolved: 2015-09-08 |
|
| Status: | Closed |
| Project: | MariaDB Connector/C |
| Component/s: | None |
| Affects Version/s: | 2.1 |
| Fix Version/s: | 2.2.0 |
| Type: | Bug | Priority: | Major |
| Reporter: | Matt Fagan | Assignee: | Georg Richter |
| Resolution: | Fixed | Votes: | 0 |
| Labels: | None | ||
| Environment: |
All |
||
| Description |
|
When using async, there is a logic error in the connect/close processing when using async but an error occurs during connection. Sample code: MYSQL* pTest, *pRes; // Create for async: // Async connect: if (pRes == nullptr) { printf("FAIL\n"); } else { printf("SUCC\n"); }; // Async close: nRV = mysql_close_start(pTest); while (nRV != 0) { nRV = mysql_close_cont(pTest, MYSQL_WAIT_WRITE | MYSQL_WAIT_READ); }; This will segfault in mysql_close_start. The problem is that when real_connect fails, it deletes the options object that indicates that the client is using async. This happens on Line 1989 of libmariadb.c. This does not occur if there is a connection/network failure in any other async function. For comparison, here is modified sample code: MYSQL* pTest, *pRes; int nRV, nRes; // Create for async: pTest = mysql_init(nullptr); mysql_options(pTest, MYSQL_OPT_NONBLOCK, 0); // Async connect: nRV = mysql_real_connect_start(&pRes, pTest, nullptr, "", "", "", 0, nullptr, 0); while (nRV != 0) { nRV = mysql_real_connect_cont(&pRes, pTest, MYSQL_WAIT_WRITE | MYSQL_WAIT_READ); } ; // Async query: nRV = mysql_query_start(&nRes, pTest, "show databases"); while (nRV != 0) { closesocket(mysql_get_socket(pTest)); nRV = mysql_query_cont(&nRes, pTest, MYSQL_WAIT_WRITE | MYSQL_WAIT_READ); }; if (nRes == 0) { printf("SUCCn"); } else { printf("FAILn"); } ; // Async close: ; This will run successfully without any segfault, because when the mysql_query_cont() call fails, it does not delete the options object. There are a few possible fixes: int STDCALL /* It is legitimate to have NULL sock argument, which will do nothing. */ mysql_close(sock); return 0; } To: mysql_close_start(MYSQL *sock) { int res; /* It is legitimate to have NULL sock argument, which will do nothing. */ if (sock && sock->net.vio) { res= mysql_close_slow_part_start(sock); /* If we need to block, return now and do the rest in mysql_close_cont(). */ if (res) return res; } mysql_close(sock); Note the only change is the if conditional, from: An alternative that would work is: |
| Comments |
| Comment by Georg Richter [ 2015-09-08 ] |
|
Thanks for your bug report and provided fix! Fixed in C/C 2.2 rev. abf0080bfa0a4255713034eb60245f2d890652da |