Skip to content

Commit a6fd09f

Browse files
committed
OpenSSL timeout fix:
Since timeout was already set via setsockopt, we call wait_io_or_timeout() with a very small timeout (5ms) to get a more precise errno, which is used by OpenSSL's error function.
1 parent 2804ed9 commit a6fd09f

File tree

2 files changed

+45
-4
lines changed

2 files changed

+45
-4
lines changed

libmariadb/secure/openssl.c

+10-4
Original file line numberDiff line numberDiff line change
@@ -567,11 +567,13 @@ my_bool ma_tls_connect(MARIADB_TLS *ctls)
567567
{
568568
switch((SSL_get_error(ssl, rc))) {
569569
case SSL_ERROR_WANT_READ:
570-
if (pvio->methods->wait_io_or_timeout(pvio, TRUE, mysql->options.connect_timeout) < 1)
570+
/* use low timeout, see ma_tls_read */
571+
if (pvio->methods->wait_io_or_timeout(pvio, TRUE, 5) < 1)
571572
try_connect= 0;
572573
break;
573574
case SSL_ERROR_WANT_WRITE:
574-
if (pvio->methods->wait_io_or_timeout(pvio, TRUE, mysql->options.connect_timeout) < 1)
575+
/* use low timeout, see ma_tls_read */
576+
if (pvio->methods->wait_io_or_timeout(pvio, TRUE, 5) < 1)
575577
try_connect= 0;
576578
break;
577579
default:
@@ -655,7 +657,10 @@ ssize_t ma_tls_read(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
655657
int error= SSL_get_error((SSL *)ctls->ssl, rc);
656658
if (error != SSL_ERROR_WANT_READ)
657659
break;
658-
if (pvio->methods->wait_io_or_timeout(pvio, TRUE, pvio->mysql->options.read_timeout) < 1)
660+
/* To get a more precise error message than "resource temporary
661+
unavailable" (=errno 11) after read timeout occured, we check
662+
the socket status using a very small timeout (=5 ms) */
663+
if (pvio->methods->wait_io_or_timeout(pvio, TRUE, 5) < 1)
659664
break;
660665
}
661666
if (rc <= 0)
@@ -676,7 +681,8 @@ ssize_t ma_tls_write(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
676681
int error= SSL_get_error((SSL *)ctls->ssl, rc);
677682
if (error != SSL_ERROR_WANT_WRITE)
678683
break;
679-
if (pvio->methods->wait_io_or_timeout(pvio, TRUE, pvio->mysql->options.write_timeout) < 1)
684+
/* use low timeout, see ma_tls_read */
685+
if (pvio->methods->wait_io_or_timeout(pvio, TRUE, 5) < 1)
680686
break;
681687
}
682688
if (rc <= 0)

unittest/libmariadb/connection.c

+35
Original file line numberDiff line numberDiff line change
@@ -2374,7 +2374,41 @@ static int test_parsec(MYSQL *my)
23742374
return OK;
23752375
}
23762376

2377+
/* Test for PR250 */
2378+
int test_tls_timeout(MYSQL *unused __attribute__((unused)))
2379+
{
2380+
unsigned int connect_timeout= 5;
2381+
unsigned int read_write_timeout= 10;
2382+
int rc;
2383+
time_t start, elapsed;
2384+
2385+
MYSQL *mysql= mysql_init(NULL);
2386+
mysql_ssl_set(mysql, NULL, NULL, NULL, NULL, NULL);
2387+
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (unsigned int *)&connect_timeout);
2388+
mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, (unsigned int *)&read_write_timeout);
2389+
mysql_options(mysql, MYSQL_OPT_WRITE_TIMEOUT, (unsigned int *)&read_write_timeout);
2390+
if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, CLIENT_REMEMBER_OPTIONS, 1))
2391+
{
2392+
mysql_close(mysql);
2393+
return FAIL;
2394+
}
2395+
2396+
start= time(NULL);
2397+
rc= mysql_query(mysql, "SET @a:=SLEEP(12)");
2398+
elapsed= time(NULL) - start;
2399+
diag("elapsed: %lu", (unsigned long)elapsed);
2400+
FAIL_IF((unsigned int)elapsed > read_write_timeout + 1, "timeout ignored");
2401+
2402+
FAIL_IF(!rc, "expected timeout error");
2403+
diag("Error: %s", mysql_error(mysql));
2404+
2405+
mysql_close(mysql);
2406+
return OK;
2407+
}
2408+
2409+
23772410
struct my_tests_st my_tests[] = {
2411+
{"test_tls_timeout", test_tls_timeout, TEST_CONNECTION_NONE, 0, NULL, NULL},
23782412
{"test_parsec", test_parsec, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
23792413
{"test_conc505", test_conc505, TEST_CONNECTION_NONE, 0, NULL, NULL},
23802414
{"test_conc632", test_conc632, TEST_CONNECTION_NONE, 0, NULL, NULL},
@@ -2423,6 +2457,7 @@ struct my_tests_st my_tests[] = {
24232457
{"test_connection_timeout", test_connection_timeout, TEST_CONNECTION_NONE, 0, NULL, NULL},
24242458
{"test_connection_timeout2", test_connection_timeout2, TEST_CONNECTION_NONE, 0, NULL, NULL},
24252459
{"test_connection_timeout3", test_connection_timeout3, TEST_CONNECTION_NONE, 0, NULL, NULL},
2460+
{"test_tls_timeout", test_tls_timeout, TEST_CONNECTION_NONE, 0, NULL, NULL},
24262461
{NULL, NULL, 0, 0, NULL, NULL}
24272462
};
24282463

0 commit comments

Comments
 (0)