This makes a couple improvements to how we wait for the socket to become ready for I/O.
First this refactors TRILOGY_RB_TIMEOUT to a "real" error status in the C library (though currently nothing in the C library raises it), which allows it to be negative like all the other errors (and avoids being confused with a successful read/write of size 1).
Next this makes _cb_ruby_wait return this new status code instead of SYSERR when there is a timeout, allowing it to propogate through trilogy_sock_upgrade_ssl and similar correctly. This allows differentiating between actually syserrors which set errno and timeouts. Also this can show the difference between rb_wait_for_single_fd returning -1 (a syscall error, which I think in practice will be extremely rare) and 0 (a timeout).
Finally the last two commits ensure that the socket is shut down on either a socket timeout we see, or from an external exception (like Timeout.timeout). For the latter we must wrap the waiting in an rb_protect, which previously we were doing correctly for queries, but not for other operations (ex. ping, change_db). We have to shut down the socket because we've interrupted normal control flow and are likely either in the middle of a write (we've partly written our packet) or a read (there will be data sent from the server that we need to handle) so any further operations are invalid.
This makes a couple improvements to how we wait for the socket to become ready for I/O.
First this refactors
TRILOGY_RB_TIMEOUT
to a "real" error status in the C library (though currently nothing in the C library raises it), which allows it to be negative like all the other errors (and avoids being confused with a successful read/write of size 1).Next this makes
_cb_ruby_wait
return this new status code instead of SYSERR when there is a timeout, allowing it to propogate throughtrilogy_sock_upgrade_ssl
and similar correctly. This allows differentiating between actually syserrors which set errno and timeouts. Also this can show the difference betweenrb_wait_for_single_fd
returning-1
(a syscall error, which I think in practice will be extremely rare) and 0 (a timeout).Finally the last two commits ensure that the socket is shut down on either a socket timeout we see, or from an external exception (like
Timeout.timeout
). For the latter we must wrap the waiting in anrb_protect
, which previously we were doing correctly for queries, but not for other operations (ex.ping
,change_db
). We have to shut down the socket because we've interrupted normal control flow and are likely either in the middle of a write (we've partly written our packet) or a read (there will be data sent from the server that we need to handle) so any further operations are invalid.