> On Mon, 2 Feb 1998, Stephen D. Williams wrote:
>
> > sigprocmask is more difficult, but no less doable. This one actually
> > I found a way to do completely in the libc library, but haven't had
> > time to actually implement. I'll describe it here since I want it
> > done so badly:
>
> ... I don't think it's possible to implement POSIX semantics in userland.
>
> > First you 'wrap' all the signal functions so that a libc signal
> > handler was the Real signal handler for all signals and that signal
> > handlers that the application registered were noted in vectors. Calls
> > to sigprocmask (and family) just modify flags in the library. When a
> > signal is triggered, the library function looks at the mask, calls the
> > real handler if unmasked, or calls the Real sigprocmask to block the
> > signal and records the pending signal. When the application unmasks
> > the signal, the library calls the real handler and upon return makes
> > the system call to Really unmask the signal.
>
> How do you deal with SA_RESTART and EINTR? If you take the signal then
> you've caused EINTR, and the application may not be expecting (or want)
> EINTR. If you use SA_RESTART for all of your handlers then as far as I
> can tell from looking at the Single Unix spec you can't choose to
> interrupt a syscall from within a signal handler... you essentially need
> to set/unset the SA_RESTART bit in the kernel for each signal.
The environment that I normally work in assumes that every system call
is either a 'fast' system call or used in async mode. Even select()
is used with a small timeout to allow for efficient polling. (Note
polling of IO, but things triggered by IO, watchdogs, etc.) We don't
use SA_RESTART. It sounds like I'd either have to settle for only
having this available in a restricted mode OR supporting this with
kernel modifications, my original plan.
> Which is great if you don't need to twiddle it fast. Unfortunately I need
> to twiddle it fast... because I need to get EINTR in some situations and
> not get it in other situations. (The application is Apache, and there's a
> critical region around accept() where I have to see EINTR, but everywhere
> else in the code I don't want to get any EINTR.)
Seems like an odd requirement, but I haven't looked at the Apache
source much yet. I can understand not wanting to handle EINTR
everywhere, but why do you need it around accept? Why not use the
async mode?
> Note that I've been able to interrupt some syscalls, but not all of them
> using a technique like this:
>
> set up SIGUSR1 with SA_RESTART and add SIGUSR2 to its sa_mask
>
> set up SIGUSR2 without SA_RESTART
>
> when a SIGUSR1 is received, raise(SIGUSR2)
>
> SIGUSR2 handler is a nop
>
> Since SIGUSR2 is blocked during the SIGUSR1 handler the SIGUSR2 isn't
> delivered until after the SIGUSR1 handler completes. Then SIGUSR2 is
> delivered and causes an EINTR... or it should. And it does for some
> syscalls (such as whatever pause() wraps), but doesn't for accept()... and
> I happen to really need it to work for accept() :)
>
> But since it appears to have similar problems on Solaris I'm just dropping
> this approach.
> Dean
Maybe there is a different way to get the effect you want that is
portable. I do need to find what's not doable in userland with my
plan. Could you detail what you think is a problem, beyond the abov3
(or possibly restating the above).
Thanks!
sdw
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu