Re: Timer, sigprocmask, etc. as memory mapped regions for performance

Dean Gaudet (dgaudet-list-linux-kernel@arctic.org)
Mon, 9 Feb 1998 01:05:06 -0800 (PST)


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.

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.)

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

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu