Hi Kristian, Well, that's awesome. Thanks for taking the time to dig into this. I have added the workaround you suggested (ignoring timeouts with a zero value), and on Monday I will check the connector github repo and test again. Best regards, Gonzalo On Sat, Sep 24, 2016 at 1:42 PM, Kristian Nielsen <knielsen@knielsen-hq.org> wrote:
Gonzalo Diethelm <gonzalo.diethelm@gmail.com> writes:
$ brew info mariadb-connector-c mariadb-connector-c: stable 2.2.2 (bottled) MariaDB database connector for C applications https://downloads.mariadb.org/connector-c/
Ok, so this is the separate client library, not the one in the server.
Notice that in the code snippet you sent, the comparison is greater than *or equal to* zero; this could in fact add a zero timeout, right?
if (vio_timeout >= 0) { b->timeout_value= vio_timeout; b->events_to_wait_for|= MYSQL_WAIT_TIMEOUT; }
Yes, you are right of course. But now I see it: For the application, zero means no timeout. Internally in the code, this is converted to -1 meaning no timeout.
And while this looks correct in the server library, the connector-c standalone library seems to do this incorrectly:
void vio_read_timeout(Vio *vio, uint timeout) { vio->read_timeout= (timeout >= 0) ? timeout * 1000 : -1; }
int vio_timeout= (mysql->options.connect_timeout >= 0) ? mysql->options.connect_timeout * 1000 : -1;
This code is comparing an unsigned value >= 0; the comparison should be >0 (an unsigned value is always >= 0, so this is obviously wrong).
So I was able to reproduce your problem with version 2.2.2 of the standalone library. However, recent changes seem to have fixed it, I could no longer reproduce. In particular it seems fixed after these three commits which seem to rewrite the I/O part of the library:
----------------------------------------------------------------------- commit a349bee53d38ee133b949b20f84ccc29d3aa4465 (refs/bisect/bad) Author: Georg Richter <georg@mariadb.com> Date: Thu Aug 6 15:10:34 2015 +0200
Added more files
commit cc85e256666a826d3247e72ea39c5332bff721bf (refs/bisect/skip- cc85e256666a826d3247e72ea39c5332bff721bf) Author: Georg Richter <georg@mariadb.com> Date: Thu Aug 6 15:08:25 2015 +0200
Added missing cio components
commit f886562fb2c411bc7ff870d75a872d906674015b (refs/bisect/skip- f886562fb2c411bc7ff870d75a872d906674015b) Author: Georg Richter <georg@mariadb.com> Date: Thu Aug 6 13:06:54 2015 +0200
Initial cio implementation -----------------------------------------------------------------------
Wlad, Georg, what are the plans for Connector-C? Will the current master branch be released as an update for the stand-alone client library? Or only as part of 10.2?
In the latter case, do you agree that a bugfix like the below patch is needed for existing stable releases of Connector-C? Since it seems that without it, timeout for non-blocking connects (and read/writes?) is completely broken?
Gonzola, thanks for bringing this to attention! If possible, you could try checking the latest git source code if your problem is indeed solved.
Otherwise, one workaround until a fix is released is to use the libmysqlclient supplied as part of the MariaDB server release.
Alternatively, change your code to interpret MYSQL_WAIT_TIMEOUT with a zero value from mysql_get_timeout_value() the same as no MYSQL_WAIT_TIMEOUT. This change will still be correct (though redundant) after the library is fixed, as MYSQL_WAIT_TIMEOUT can never legally have a zero timeout.
Thanks,
- Kristian.
diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index 8fd87ba..23aa407 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -254,7 +254,7 @@ static int connect_sync_or_async(MYSQL *mysql, NET *net, my_socket fd, const struct sockaddr *name, uint namelen) { - int vio_timeout= (mysql->options.connect_timeout >= 0) ? + int vio_timeout= (mysql->options.connect_timeout > 0) ? mysql->options.connect_timeout * 1000 : -1;
if (mysql->options.extension && mysql->options.extension->async_context && @@ -1767,7 +1767,7 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user, vio_write_timeout(net->vio, mysql->options.read_timeout); /* Get version info */ mysql->protocol_version= PROTOCOL_VERSION; /* Assume this */ - if (mysql->options.connect_timeout >= 0 && + if (mysql->options.connect_timeout > 0 && vio_wait_or_timeout(net->vio, FALSE, mysql->options.connect_timeout * 1000) < 1) { my_set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN, diff --git a/libmariadb/violite.c b/libmariadb/violite.c index 1fbdcc3..722724f 100644 --- a/libmariadb/violite.c +++ b/libmariadb/violite.c @@ -127,13 +127,13 @@ void vio_timeout(Vio *vio, int type, uint timeval)
void vio_read_timeout(Vio *vio, uint timeout) { - vio->read_timeout= (timeout >= 0) ? timeout * 1000 : -1; + vio->read_timeout= (timeout > 0) ? timeout * 1000 : -1; vio_timeout(vio, SO_RCVTIMEO, vio->read_timeout); }
void vio_write_timeout(Vio *vio, uint timeout) { - vio->write_timeout= (timeout >= 0) ? timeout * 1000 : -1; + vio->write_timeout= (timeout > 0) ? timeout * 1000 : -1; vio_timeout(vio, SO_SNDTIMEO, vio->write_timeout); }
-- Gonzalo Diethelm gonzalo.diethelm@gmail.com