← Back to team overview

maria-developers team mailing list archive

Re: mysql_get_timeout_value returning 0 always

 

Gonzalo Diethelm <gonzalo.diethelm@xxxxxxxxx> writes:

> In my code, I am calling mysql_real_connect_start(), and the return value
> indicates that MySQL is waiting for READ and TIMEOUT. However, if I call
> mysql_get_timeout_value() (or the _ms() version) right after that, it
> returns 0. Is this expected? As far as I can see, this is causing the next

No, it is not expected. MYSQL_WAIT_TIMEOUT should only be returned in status
if a non-zero MYSQL_OPT_CONNECT_TIMEOUT is set with mysql_options().

> This is on OS X 10.11.6 with the MariaDB client just installed via brew;
> mariadb_config --version says 5.5.1.

Hm. Can you clarify exactly which version of the library you are using? Are
you using the library that is bundled with the server (seems likely since
you are using the async_queries.c example from the server source tree)? Or
are you using the separate connector-c library?

Version 5.5.1 of the server did not include the non-blocking library...

> This is the code I'm calling:
>
>             status = mysql_real_connect_start(&ret, &mysql, h, u, p, d, 0,
> 0, 0);
>             printf("MYSQL connect %d", status);
>             if (status & MYSQL_WAIT_TIMEOUT) {
>                 unsigned int ms = mysql_get_timeout_value_ms(&mysql);
>                 printf(" and includes a timeout of %u ms", ms);
>             }
>             printf("\n");

I tried adding this to async_queries.c, but I could not reproduce. I get

  MYSQL connect 2

If I add to the source

    unsigned int my_timeout = 10;
    mysql_options(&sds[i].mysql, MYSQL_OPT_CONNECT_TIMEOUT, &my_timeout);

I get:

  MYSQL connect 10 and includes a timeout of 10000 ms

Can you try to apply the attached patch to async_queries.c and see if you
can reproduce the problem with that code? If so, maybe it is something
specific to OS X? If not, then maybe something goes wrong in your code?

> That code prints: MYSQL connect 9 and includes a timeout of 0 ms

The thing is, the only places in the code that set MYSQL_WAIT_TIMEOUT() look
like this:

    if (vio_timeout >= 0)
    {
      b->timeout_value= vio_timeout;
      b->events_to_wait_for|= MYSQL_WAIT_TIMEOUT;
    }

And mysql_get_timeout_value_ms() basically returns b->timeout_value. So it
is surprising to see your code getting MYSQL_WAIT_TIMEOUT with a zero value
for timeout...

> I did find two ways to make the code work:
>
>    1. Not passing MYSQL_WAIT_TIMEOUT back to the mysql_real_connect_cont()
>    (so it thinks a timeout has not happened at all). This allows all the
>    queries to actually complete, but the code ends up polling heavily.

Not passing MYSQL_WAIT_TIMEOUT back should not cause any polling (though it
will disable the timeout functionality). But nor should it be necessary to
special case this, obviously.

Hope this helps,

 - Kristian.

diff --git a/tests/async_queries.c b/tests/async_queries.c
index 76e884e..486458c 100644
--- a/tests/async_queries.c
+++ b/tests/async_queries.c
@@ -168,6 +168,12 @@ state_machine_handler(int fd __attribute__((unused)), short event, void *arg)
   case 0:
     /* Initial state, start making the connection. */
     status= mysql_real_connect_start(&sd->ret, &sd->mysql, opt_host, opt_user, opt_password, opt_db, opt_port, opt_socket, 0);
+    printf("MYSQL connect %d", status);
+    if (status & MYSQL_WAIT_TIMEOUT) {
+      unsigned int ms = mysql_get_timeout_value_ms(&sd->mysql);
+      printf(" and includes a timeout of %u ms", ms);
+    }
+    printf("\n");
     if (status)
       /* Wait for connect to complete. */
       next_event(1, status, sd);
@@ -410,9 +416,11 @@ main(int argc, char *argv[])
   num_active_connections= 0;
   for (i= 0; i < opt_connections; i++)
   {
+    unsigned int my_timeout = 10;
     mysql_init(&sds[i].mysql);
     mysql_options(&sds[i].mysql, MYSQL_OPT_NONBLOCK, 0);
     mysql_options(&sds[i].mysql, MYSQL_READ_DEFAULT_GROUP, "async_queries");
+    mysql_options(&sds[i].mysql, MYSQL_OPT_CONNECT_TIMEOUT, &my_timeout);
 
     /*
       We put the initial connect call in the first state 0 of the state machine

Follow ups

References