1
1
#include <mysql2_ext.h>
2
2
3
+ #include <time.h>
3
4
#include <errno.h>
4
5
#ifndef _WIN32
5
6
#include <sys/types.h>
@@ -255,6 +256,7 @@ static VALUE allocate(VALUE klass) {
255
256
wrapper -> active_thread = Qnil ;
256
257
wrapper -> server_version = 0 ;
257
258
wrapper -> reconnect_enabled = 0 ;
259
+ wrapper -> connect_timeout = 0 ;
258
260
wrapper -> connected = 0 ; /* means that a database connection is open */
259
261
wrapper -> initialized = 0 ; /* means that that the wrapper is initialized */
260
262
wrapper -> refcount = 1 ;
@@ -326,6 +328,8 @@ static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE po
326
328
struct nogvl_connect_args args ;
327
329
VALUE rv ;
328
330
GET_CLIENT (self );
331
+ time_t start_time , end_time ;
332
+ unsigned int elapsed_time , connect_timeout ;
329
333
330
334
args .host = NIL_P (host ) ? NULL : StringValuePtr (host );
331
335
args .unix_socket = NIL_P (socket ) ? NULL : StringValuePtr (socket );
@@ -336,12 +340,31 @@ static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE po
336
340
args .mysql = wrapper -> client ;
337
341
args .client_flag = NUM2ULONG (flags );
338
342
343
+ if (wrapper -> connect_timeout )
344
+ time (& start_time );
339
345
rv = (VALUE ) rb_thread_call_without_gvl (nogvl_connect , & args , RUBY_UBF_IO , 0 );
340
346
if (rv == Qfalse ) {
341
- while (rv == Qfalse && errno == EINTR && !mysql_errno (wrapper -> client )) {
347
+ while (rv == Qfalse && errno == EINTR ) {
348
+ if (wrapper -> connect_timeout ) {
349
+ time (& end_time );
350
+ /* avoid long connect timeout from system time changes */
351
+ if (end_time < start_time )
352
+ start_time = end_time ;
353
+ elapsed_time = end_time - start_time ;
354
+ /* avoid an early timeout due to time truncating milliseconds off the start time */
355
+ if (elapsed_time > 0 )
356
+ elapsed_time -- ;
357
+ if (elapsed_time >= wrapper -> connect_timeout )
358
+ break ;
359
+ connect_timeout = wrapper -> connect_timeout - elapsed_time ;
360
+ mysql_options (wrapper -> client , MYSQL_OPT_CONNECT_TIMEOUT , & connect_timeout );
361
+ }
342
362
errno = 0 ;
343
363
rv = (VALUE ) rb_thread_call_without_gvl (nogvl_connect , & args , RUBY_UBF_IO , 0 );
344
364
}
365
+ /* restore the connect timeout for reconnecting */
366
+ if (wrapper -> connect_timeout )
367
+ mysql_options (wrapper -> client , MYSQL_OPT_CONNECT_TIMEOUT , & wrapper -> connect_timeout );
345
368
if (rv == Qfalse )
346
369
return rb_raise_mysql2_error (wrapper );
347
370
}
@@ -795,9 +818,15 @@ static VALUE _mysql_client_options(VALUE self, int opt, VALUE value) {
795
818
if (result != 0 ) {
796
819
rb_warn ("%s\n" , mysql_error (wrapper -> client ));
797
820
} else {
798
- /* Special case for reconnect, this option is also stored in the wrapper struct */
799
- if (opt == MYSQL_OPT_RECONNECT )
800
- wrapper -> reconnect_enabled = boolval ;
821
+ /* Special case for options that are stored in the wrapper struct */
822
+ switch (opt ) {
823
+ case MYSQL_OPT_RECONNECT :
824
+ wrapper -> reconnect_enabled = boolval ;
825
+ break ;
826
+ case MYSQL_OPT_CONNECT_TIMEOUT :
827
+ wrapper -> connect_timeout = intval ;
828
+ break ;
829
+ }
801
830
}
802
831
803
832
return (result == 0 ) ? Qtrue : Qfalse ;
0 commit comments