Skip to content

Commit cc06286

Browse files
committed
Hand-off GVL during connect
1 parent 206898d commit cc06286

File tree

3 files changed

+60
-4
lines changed

3 files changed

+60
-4
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
* `TinyTds::Client.new` now accepts keyword arguments instead of a hash
1111
* Renamed `tds_version` and `tds_version_info` to `server_version` and `server_version_info`
1212
* Separate `#new` and `#connect`
13-
* Instead, before running `#do`, `#execute` or `#insert`, `tiny_tds` will check if the connection is active and re-connect if needed.
13+
* Instead, before running `#do`, `#execute` or `#insert`, `tiny_tds` will check if the connection is active and re-connect if needed.+
14+
* `#connect` hands off the GVL when communicating with the server. Fixes #421.
1415

1516
## 3.3.0
1617

ext/tiny_tds/client.c

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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

946967
static 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);

test/client_test.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,17 @@ class ClientTest < TinyTds::TestCase
200200
end
201201
assert_new_connections_work
202202
end
203+
204+
it "raises TinyTds exception with invalid database name" do
205+
action = lambda { new_connection(database: "DOESNOTEXIST") }
206+
assert_raise_tinytds_error(action) do |e|
207+
assert_equal 911, e.db_error_number
208+
assert_equal 16, e.severity
209+
assert_equal "Database 'DOESNOTEXIST' does not exist. Make sure that the name is entered correctly.", e.message
210+
end
211+
212+
assert_new_connections_work
213+
end
203214
end
204215

205216
describe "#parse_username" do

0 commit comments

Comments
 (0)