Attempting to escape large, untrusted strings cause stack
overflows (easier under Ruby 1.9 using pthreads) leading to
SystemStackError on small overflows and segmentation faults on
large overflows. Instead of allocating on the stack, we'll
allocate a string buffer from the heap.
This has the unfortunate effect of reducing escape performance
for common cases, but in my experience SQL escaping isn't much
of a bottleneck.
For reference, Ruby 1.9.2-p0 with pthreads gets a stack size of
512K and the default process stack size is 8MB on both x86 and
x86_64 Linux.
This reverts the single-threaded select() optimization from
commits 9a63a587c0 and
0190457dbd.
Under Ruby 1.9, the reverted optimization caused signal handlers
to be delayed until the socket became readable.
Under Ruby 1.8, matters are worse as receiving a signal during
select() causes Errno::EINTR to be raised.
There is now a (somewhat fragile) spec for testing signal
handling during a "SELECT sleep(2)" query.
Furthermore, the performance difference I measured on
benchmark/thread_alone.rb was negligible (over 1000 iterations)
between the two:
Ruby 1.8.7-p249
Rehearsal ----------------------------------------------------
select 0.040000 0.020000 0.060000 ( 0.119448)
rb_thread_select 0.050000 0.020000 0.070000 ( 0.132091)
------------------------------------------- total: 0.130000sec
user system total real
select 0.030000 0.030000 0.060000 ( 0.116471)
rb_thread_select 0.050000 0.020000 0.070000 ( 0.119874)
Ruby 1.9.2-p0
Rehearsal ----------------------------------------------------
select 0.050000 0.030000 0.080000 ( 0.134208)
rb_thread_select 0.080000 0.000000 0.080000 ( 0.141316)
------------------------------------------- total: 0.160000sec
user system total real
select 0.050000 0.020000 0.070000 ( 0.123325)
rb_thread_select 0.060000 0.010000 0.070000 ( 0.124075)
Benchmarks were performed on an _empty_ mysql2_test table to
maximize the relative time for the select(2)-related code path
(vs reading data). The test was run on Debian Lenny, x86_64 and
a stock 2.6.35.2 Linux kernel. Hardware was a Core2 Duo @
1.6GHz with the performance CPU governor while on AC power
to eliminate CPU speed fluctuations during the test.
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.