[freetds] EINTR bug solved
James K. Lowden
jklowden at freetds.org
Tue Oct 23 22:49:47 EDT 2007
(If you didn't know there was an EINTR bug, you're not alone.)
I just committed a new version of src/tds/net.c::tds_select(). The old
version incorrectly dropped to an assert(rc == 0) when trying to handle
EINTR, such as is produced when pressing ^C (sending SIGINT) in sqsh or
fisql. The new version permits these programs to work correctly.
On receipt of a signal, select(2) returns an error and errno is set to
EINTR. The descriptor sets are unmodified, meaning select can be called
again without reinitializing anything. However, whether or not that's the
right thing to do depends on the signal caught and how the application
When EINTR is detected, tds_select() treats it like a timeout. If an
interrupt handler was installed, it's called, and the application can
thereby indicate whether to retry or abort. If retry, select(2) is called
again, just as though nothing ever happened.
I also simplified the code somewhat. It's important we do *not* call e.g.
gettimeofday() within the poll loop. The right thing to do is simply to
count down the seconds, because the system's time can change. If it does,
we don't want to change the application's timeout. (The timeout is
counted in seconds, not as a time of day.)
db-lib interrupt handling is still a little rough around the edges. fisql
stays on its feet after ^C, but only after printing a bogus error message.
More information about the FreeTDS