Abolishing sleeps in issignal()
Matthew Dillon
dillon at apollo.backplane.com
Tue Oct 9 16:49:08 PDT 2007
I think it's a bad idea to have SIGSTOP generate an EINTR-like event.
The two have totally different mechanics and the system call behavior
will be different because there are some system calls which simply cannot
be restarted even if you wanted to. System calls which loop on UIO's,
for example, cannot be restarted. EINTR and STOP have two totally
different behaviors for such calls and there is nothing you can do about
it. Basically any system call which maintains state through multiple
blocking events cannot be restarted after having returned unless no
cumulative operations have been performed.
For example, if read()ing from a socket the read() is restartable ONLY
if no data has yet been read. But if some data HAS been read and EINTR
occurs, the system call will simply terminate early and return a
short-read, and NOT restart. That same system call when presented with
a STOP, however, will not terminate early. Instead it (in FreeBSD now)
stops in tsleep and when it is CONTed again the system call resumes.
It's simply not possible (without a LOT of work) to have such a system
call return all the way to userland or even return to the kernel syscall
trap layer and be able to restart it.
The restart code only works if no cumulative events have occured... for
example, if a UIO has not been filled at all (0 bytes read or written).
ERESTART literally moves the program counter back to the start of the
system call and causes userland to re-execute it.
The best compromise that I found, which I implemented for Dragonfly a
while back, was to ignore SIGSTOP in the kernel entirely and process
the event in userret() instead. Except for certain process control
cases like the debugger, SIGSTOP is handled asynchronously anyway. e.g.
when you signal a SIGSTOP the kill() system call will return before
the target process(es) have actually stopped. It's just that the window
of opportunity is fairly small when SIGSTOP is handled in tsleep, and
somewhat bigger when it is handled in userret. That's the only hangup.
-Matt
More information about the freebsd-arch
mailing list