Date: Tue, 9 Oct 2007 16:49:00 -0700 (PDT) From: Matthew Dillon <dillon@apollo.backplane.com> To: Kostik Belousov <kostikbel@gmail.com> Cc: arch@freebsd.org Subject: Re: Abolishing sleeps in issignal() Message-ID: <200710092349.l99Nn01S073431@apollo.backplane.com> References: <20071008142928.Y912@10.0.0.1> <20071009100259.GW2180@deviant.kiev.zoral.com.ua>
next in thread | previous in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200710092349.l99Nn01S073431>