From d8abc9d91a6eb4e1a5a4293060c00881e69caf93 Mon Sep 17 00:00:00 2001 From: Matias Martini Date: Sat, 11 Mar 2023 02:06:15 -0300 Subject: [PATCH 1/2] Test(client): Add dead test after closing client We recently encountered an unexpected Segmentation Fault Error when checking whether a client was dead after closing it. To consider this in the future, I've updated the test cases for the client to include this scenario, so we can catch any issues earlier on. --- test/client_test.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/client_test.rb b/test/client_test.rb index de988d6e..d095db71 100644 --- a/test/client_test.rb +++ b/test/client_test.rb @@ -16,6 +16,7 @@ class ClientTest < TinyTds::TestCase assert @client.close assert @client.closed? assert !@client.active? + assert @client.dead? action = lambda { @client.execute('SELECT 1 as [one]').each } assert_raise_tinytds_error(action) do |e| assert_match %r{closed connection}i, e.message, 'ignore if non-english test run' From 7fe8c8eb2411eda69fb2c9b5585c5e0016ce0e33 Mon Sep 17 00:00:00 2001 From: Matias Martini Date: Sat, 11 Mar 2023 02:13:27 -0300 Subject: [PATCH 2/2] Fix(client) Set dangling pointer to NULL after client closure We recently encountered an unexpected Segmentation Fault Error while checking if a client was dead after closing it. Upon investigation, we discovered that the issue was caused by deallocating all memory used by the client structure without setting the pointer to NULL after closing the client connection through dbclose. This resulted in a dangling pointer, which led to the Segmentation Fault when we tried to check whether the client was dead using TDS dbdead. To prevent this issue from occurring again, I have made the necessary updates to set the client pointer to NULL after every dbclose. This will ensure that we avoid any dangling pointers and keep our code running smoothly. --- CHANGELOG.md | 1 + ext/tiny_tds/client.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8c0b5a1..23669780 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## (unreleased) * Add Ruby 3.0 to the cross compile list +* Fix segfault when asking if client was dead after closing it. Fixes #519. ## 2.1.5 diff --git a/ext/tiny_tds/client.c b/ext/tiny_tds/client.c index 1fb0ba6e..ea01d144 100644 --- a/ext/tiny_tds/client.c +++ b/ext/tiny_tds/client.c @@ -232,6 +232,7 @@ static void rb_tinytds_client_free(void *ptr) { dbloginfree(cwrap->login); if (cwrap->client && !cwrap->closed) { dbclose(cwrap->client); + cwrap->client = NULL; cwrap->closed = 1; cwrap->userdata->closed = 1; } @@ -263,6 +264,7 @@ static VALUE rb_tinytds_close(VALUE self) { GET_CLIENT_WRAPPER(self); if (cwrap->client && !cwrap->closed) { dbclose(cwrap->client); + cwrap->client = NULL; cwrap->closed = 1; cwrap->userdata->closed = 1; }