make Mysql2::Client destructor safely non-blocking
Since sending a QUIT message to the MySQL server is more of a formality than a hard requirement in a TCP-based protocol, we'll just fire-and-forget the message to avoid any chance of blocking the interpreter during the GC finalizer phase. Since the socket will be closed immediately afterwards, there's no long-term side-effects from making the socket non-blocking. We do this instead of using rb_thread_blocking_region because the GVL is already destroyed by the time the ObjectSpace finalizers are called under 1.9.
This commit is contained in:
parent
46021b9351
commit
ec00873181
@ -187,10 +187,23 @@ static void rb_mysql_client_free(void * ptr) {
|
|||||||
|
|
||||||
if (client->client) {
|
if (client->client) {
|
||||||
/*
|
/*
|
||||||
* this may send a "QUIT" message to the server and thus block
|
* we'll send a QUIT message to the server, but that message is more of a
|
||||||
* on the socket write, users are encouraged to close this manually
|
* formality than a hard requirement since the socket is getting shutdown
|
||||||
* to avoid this behavior
|
* anyways, so ensure the socket write does not block our interpreter
|
||||||
*/
|
*/
|
||||||
|
int fd = client->client->net.fd;
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
if (fd >= 0) {
|
||||||
|
/*
|
||||||
|
* if the socket is dead we have no chance of blocking,
|
||||||
|
* so ignore any potential fcntl errors since they don't matter
|
||||||
|
*/
|
||||||
|
flags = fcntl(fd, F_GETFL);
|
||||||
|
if (flags > 0 && !(flags & O_NONBLOCK))
|
||||||
|
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
||||||
|
}
|
||||||
|
|
||||||
mysql_close(client->client);
|
mysql_close(client->client);
|
||||||
}
|
}
|
||||||
xfree(ptr);
|
xfree(ptr);
|
||||||
@ -204,8 +217,8 @@ static VALUE nogvl_close(void * ptr) {
|
|||||||
/*
|
/*
|
||||||
* Immediately disconnect from the server, normally the garbage collector
|
* Immediately disconnect from the server, normally the garbage collector
|
||||||
* will disconnect automatically when a connection is no longer needed.
|
* will disconnect automatically when a connection is no longer needed.
|
||||||
* Explicitly closing this can free up server resources sooner and is
|
* Explicitly closing this will free up server resources sooner than waiting
|
||||||
* also 100% safe when faced with signals or running multithreaded
|
* for the garbage collector.
|
||||||
*/
|
*/
|
||||||
static VALUE rb_mysql_client_close(VALUE self) {
|
static VALUE rb_mysql_client_close(VALUE self) {
|
||||||
mysql2_client_wrapper *client;
|
mysql2_client_wrapper *client;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include <ruby.h>
|
#include <ruby.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
#ifdef HAVE_MYSQL_H
|
#ifdef HAVE_MYSQL_H
|
||||||
#include <mysql.h>
|
#include <mysql.h>
|
||||||
|
Loading…
Reference in New Issue
Block a user