trilogy-libraries / trilogy

Trilogy is a client library for MySQL-compatible database servers, designed for performance, flexibility, and ease of embedding.
MIT License
700 stars 69 forks source link

Improve wait callback and timeout handling #110

Closed jhawthorn closed 1 year ago

jhawthorn commented 1 year ago

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.