Skip to content

Commit 56f6d54

Browse files
committed
Merge pull request #447 from sodabrew/no_dangling_connections
Specs and refactor of #444 preventing dangling connections
2 parents c514179 + 4aa9b14 commit 56f6d54

File tree

4 files changed

+27
-18
lines changed

4 files changed

+27
-18
lines changed

ext/mysql2/client.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,16 @@ static void *nogvl_close(void *ptr) {
196196

197197
static void rb_mysql_client_free(void *ptr) {
198198
mysql_client_wrapper *wrapper = (mysql_client_wrapper *)ptr;
199+
decr_mysql2_client(wrapper);
200+
}
199201

202+
void decr_mysql2_client(mysql_client_wrapper *wrapper)
203+
{
200204
wrapper->refcount--;
201205
if (wrapper->refcount == 0) {
202-
close_connection_and_free_mysql2_client(wrapper);
206+
nogvl_close(wrapper);
207+
xfree(wrapper->client);
208+
xfree(wrapper);
203209
}
204210
}
205211

@@ -1309,12 +1315,3 @@ void init_mysql2_client() {
13091315
LONG2NUM(CLIENT_BASIC_FLAGS));
13101316
#endif
13111317
}
1312-
1313-
void close_connection_and_free_mysql2_client(void *ptr) {
1314-
mysql_client_wrapper *wrapper = (mysql_client_wrapper *)ptr;
1315-
1316-
nogvl_close(wrapper);
1317-
xfree(wrapper->client);
1318-
xfree(wrapper);
1319-
}
1320-

ext/mysql2/client.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,6 @@ rb_thread_call_without_gvl(
3636
#endif /* ! HAVE_RB_THREAD_BLOCKING_REGION */
3737
#endif /* ! HAVE_RB_THREAD_CALL_WITHOUT_GVL */
3838

39-
void init_mysql2_client();
40-
void close_connection_and_free_mysql2_client(void *);
41-
4239
typedef struct {
4340
VALUE encoding;
4441
VALUE active_thread; /* rb_thread_current() or Qnil */
@@ -51,4 +48,7 @@ typedef struct {
5148
MYSQL *client;
5249
} mysql_client_wrapper;
5350

51+
void init_mysql2_client();
52+
void decr_mysql2_client(mysql_client_wrapper *wrapper);
53+
5454
#endif

ext/mysql2/result.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#include <mysql2_ext.h>
22
#include <stdint.h>
33

4-
#include "client.h"
54
#include "mysql_enc_to_ruby.h"
65

76
#ifdef HAVE_RUBY_ENCODING_H
@@ -85,10 +84,7 @@ static void rb_mysql_result_free(void *ptr) {
8584

8685
// If the GC gets to client first it will be nil
8786
if (wrapper->client != Qnil) {
88-
wrapper->client_wrapper->refcount--;
89-
if (wrapper->client_wrapper->refcount == 0) {
90-
close_connection_and_free_mysql2_client(wrapper->client_wrapper);
91-
}
87+
decr_mysql2_client(wrapper->client_wrapper);
9288
}
9389

9490
xfree(wrapper);

spec/mysql2/client_spec.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,22 @@ def connect *args
104104
ssl_client.close
105105
end
106106

107+
it "should not leave dangling connections after garbage collection" do
108+
GC.start
109+
client = Mysql2::Client.new(DatabaseCredentials['root'])
110+
before_count = client.query("SHOW STATUS LIKE 'Threads_connected'").first['Value'].to_i
111+
112+
10.times do
113+
Mysql2::Client.new(DatabaseCredentials['root']).query('SELECT 1')
114+
end
115+
after_count = client.query("SHOW STATUS LIKE 'Threads_connected'").first['Value'].to_i
116+
after_count.should == before_count + 10
117+
118+
GC.start
119+
final_count = client.query("SHOW STATUS LIKE 'Threads_connected'").first['Value'].to_i
120+
final_count.should == before_count
121+
end
122+
107123
it "should be able to connect to database with numeric-only name" do
108124
lambda {
109125
creds = DatabaseCredentials['numericuser']

0 commit comments

Comments
 (0)