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.
Data_Make_Struct always allocates memory for us, so we
need to explicitly free the pointer in the function we
pass to the GC, not just objects internal to us.
Without this change, a slow but constant growth can be
seen with the trivial code below:
x = Mysql2::Client.new
loop { x.query "select 1" }
This allows users to (manually) avoid the tricky case of hitting
a socket write during GC and potentially blocking the
interpreter during GC. An explicit `close' is also useful in
situations where server resources are limited and a client only
needs to connect for a limited time.
Other than the Init_$extension() function, the only reason
to have public symbols is for large C extensions that need
to span multiple .c files and we're not one of them.
This can help us notice real bugs in our code sooner.
Some of the unused variable warnings are pedantic from our usage
of -Wextra, but GCC >= 3 provides us with a handy attribute we
can use to mark variables unused. -Wextra is also a default
flag for 1.9.2dev, so we might as well get used to it.
There are still some corner-case calls which may cause
network activity and block the socket, but the majority
of reads/writes on the socket will release the GVL under
1.9 and be signal-safe under all versions of Ruby.
We'll also make a note of all functions calls that passed
visual inspection and add FIXME for a few more corner
cases we still need to fix.
mysql_real_connect() is a blocking function that issues
blocking-but-interruptible connect(), read(), and write() system
calls. So we'll allow other threads in the VM to run while
calling it since it can block indefinitely.
This introduces a rb_thread_blocking_region() wrapper for 1.8
which ensures any received signals can be handled gracefully
while inside blocking function calls.
This allows the caller to iterate over the Mysql2::Result instance as many times as they want, lazily pulling what rows are needed from the mysql C result.