Hi,
Why would SIGVTALRM ever cause IO#sysread to throw EINTR? I’m having
a problem where a Net::HTTP connection is repeatedly dying because its
IO#sysread call is being interrupted and raising EINTR. I have
attached strace to the process, and verified that the signal being
raised is SIGVTALRM.
What I don’t understand is why SIGVTALRM would ever interrupt a system
call. the setitimer(2) documentation says that the ITIMER_VIRTUAL
timer only decrements when the process is executing. So why would
the signal fire when I’m blocked on a system call (eg. when my process
is not executing)?
I notice that up until recently, signal handlers for all signals
except SIGVTALRM were installed with the SA_RESTART flag, which would
make read(2) retry instead of returning EINTR when a signal was
received. (I’m still using a version of Ruby that has this
behavior). Why did Ruby specifically not set SA_RESTART for
SIGVTALRM? I’m guessing the rationale has something to do with
allowing Ruby to run its thread scheduler. But this doesn’t make
sense to me for two reasons:
-
the Ruby interpreter already takes measures to ensure that it never
blocks on a system call if there are other runnable threads. So when
would it ever be blocked on a system call, but have other threads it
wants to schedule by receiving SIGVTALRM? -
again, according to the setitimer(2) documentation, it doesn’t make
sense that SIGVTALRM would ever be raised when blocked on a system
call. So why should not setting SA_RESTART have any effect?
Any help is much appreciated!
Josh
P.S. Does the change in 1.8.6 of not setting SA_RESTART with
sigaction(2) mean that Ruby scripts now need to handle EINTR in many
places they did not previously have to?