@@ -209,32 +209,19 @@ static VALUE invalidate_fd(int clientfd)
209
209
#endif /* _WIN32 */
210
210
211
211
static void * nogvl_close (void * ptr ) {
212
- mysql_client_wrapper * wrapper ;
213
- wrapper = ptr ;
214
- if (wrapper -> connected ) {
215
- MARK_CONN_INACTIVE (self );
216
- wrapper -> connected = 0 ;
217
- #ifndef _WIN32
218
- /* Invalidate the socket before calling mysql_close(). This prevents
219
- * mysql_close() from sending a mysql-QUIT or from calling shutdown() on
220
- * the socket. The difference is that invalidate_fd will drop this
221
- * process's reference to the socket only, while a QUIT or shutdown()
222
- * would render the underlying connection unusable, interrupting other
223
- * processes which share this object across a fork().
224
- */
225
- if (invalidate_fd (wrapper -> client -> net .fd ) == Qfalse ) {
226
- fprintf (stderr , "[WARN] mysql2 failed to invalidate FD safely, leaking some memory\n" );
227
- close (wrapper -> client -> net .fd );
228
- return NULL ;
229
- }
230
- #endif
212
+ mysql_client_wrapper * wrapper = ptr ;
231
213
232
- mysql_close (wrapper -> client ); /* only used to free memory at this point */
214
+ if (wrapper -> client ) {
215
+ mysql_close (wrapper -> client );
216
+ wrapper -> client = NULL ;
217
+ wrapper -> connected = 0 ;
218
+ wrapper -> active_thread = Qnil ;
233
219
}
234
220
235
221
return NULL ;
236
222
}
237
223
224
+ /* this is called during GC */
238
225
static void rb_mysql_client_free (void * ptr ) {
239
226
mysql_client_wrapper * wrapper = (mysql_client_wrapper * )ptr ;
240
227
decr_mysql2_client (wrapper );
@@ -245,6 +232,22 @@ void decr_mysql2_client(mysql_client_wrapper *wrapper)
245
232
wrapper -> refcount -- ;
246
233
247
234
if (wrapper -> refcount == 0 ) {
235
+ #ifndef _WIN32
236
+ if (wrapper -> connected ) {
237
+ /* The client is being garbage collected while connected. Prevent
238
+ * mysql_close() from sending a mysql-QUIT or from calling shutdown() on
239
+ * the socket by invalidating it. invalidate_fd() will drop this
240
+ * process's reference to the socket only, while a QUIT or shutdown()
241
+ * would render the underlying connection unusable, interrupting other
242
+ * processes which share this object across a fork().
243
+ */
244
+ if (invalidate_fd (wrapper -> client -> net .fd ) == Qfalse ) {
245
+ fprintf (stderr , "[WARN] mysql2 failed to invalidate FD safely\n" );
246
+ close (wrapper -> client -> net .fd );
247
+ }
248
+ }
249
+ #endif
250
+
248
251
nogvl_close (wrapper );
249
252
xfree (wrapper -> client );
250
253
xfree (wrapper );
@@ -378,10 +381,13 @@ static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE po
378
381
}
379
382
380
383
/*
381
- * Immediately disconnect from the server, normally the garbage collector
382
- * will disconnect automatically when a connection is no longer needed.
383
- * Explicitly closing this will free up server resources sooner than waiting
384
- * for the garbage collector.
384
+ * Terminate the connection; call this when the connection is no longer needed.
385
+ * The garbage collector can close the connection, but doing so emits an
386
+ * "Aborted connection" error on the server and increments the Aborted_clients
387
+ * status variable.
388
+ *
389
+ * @see http://dev.mysql.com/doc/en/communication-errors.html
390
+ * @return [void]
385
391
*/
386
392
static VALUE rb_mysql_client_close (VALUE self ) {
387
393
GET_CLIENT (self );
0 commit comments