@@ -939,9 +939,30 @@ static VALUE rb_tinytds_identity_sql(VALUE self)
939939 return rb_str_new2 (cwrap -> identity_insert_sql );
940940}
941941
942+ // connect function, with some additions to enable handing off the GVL
943+ struct dbopen_args {
944+ LOGINREC * login ;
945+ const char * dataserver ;
946+ };
947+
948+ struct dbuse_args {
949+ DBPROCESS * dbproc ;
950+ const char * name ;
951+ };
942952
953+ static void * dbopen_without_gvl (void * ptr )
954+ {
955+ struct dbopen_args * args = (struct dbopen_args * )ptr ;
956+ return dbopen (args -> login , args -> dataserver );
957+ }
943958
944- // TinyTds::Client (protected)
959+ static void *
960+ dbuse_without_gvl (void * ptr )
961+ {
962+ struct dbuse_args * args = (struct dbuse_args * )ptr ;
963+ dbuse (args -> dbproc , args -> name );
964+ return NULL ;
965+ }
945966
946967static VALUE rb_tinytds_connect (VALUE self )
947968{
@@ -1011,7 +1032,19 @@ static VALUE rb_tinytds_connect(VALUE self)
10111032 DBSETLUTF16 (cwrap -> login , 0 );
10121033 }
10131034
1014- cwrap -> client = dbopen (cwrap -> login , StringValueCStr (dataserver ));
1035+ // we normally have our nice NOGVL_DBCALL macro, but "dbopen" requires different arguments
1036+ struct dbopen_args open_args ;
1037+ open_args .login = cwrap -> login ;
1038+ open_args .dataserver = StringValueCStr (dataserver );
1039+
1040+ cwrap -> client = (DBPROCESS * )rb_thread_call_without_gvl (
1041+ dbopen_without_gvl ,
1042+ & open_args ,
1043+ // compared to any other database call, we cannot cancel the login to the database
1044+ // in any meaningful way, so unblock function remains empty
1045+ NULL ,
1046+ NULL
1047+ );
10151048
10161049 if (cwrap -> client ) {
10171050 if (dbtds (cwrap -> client ) < 11 ) {
@@ -1040,7 +1073,18 @@ static VALUE rb_tinytds_connect(VALUE self)
10401073 cwrap -> userdata -> closed = 0 ;
10411074
10421075 if (!NIL_P (database ) && (azure != Qtrue )) {
1043- dbuse (cwrap -> client , StringValueCStr (database ));
1076+ struct dbuse_args use_args ;
1077+ use_args .dbproc = cwrap -> client ;
1078+ use_args .name = StringValueCStr (database );
1079+
1080+ // in case of any errors, the tinytds_err_handler will be called
1081+ // so we do not have to check the return code here
1082+ rb_thread_call_without_gvl (
1083+ dbuse_without_gvl ,
1084+ & use_args ,
1085+ NULL ,
1086+ NULL
1087+ );
10441088 }
10451089
10461090 transposed_encoding = rb_funcall (cTinyTdsClient , intern_transpose_iconv_encoding , 1 , charset );
0 commit comments