Re: [patch 1/4] signalfd v1 - signalfd core ...

From: Davide Libenzi
Date: Fri Mar 16 2007 - 02:36:04 EST


On Thu, 15 Mar 2007, Ulrich Drepper wrote:

> On 3/7/07, Davide Libenzi <davidel@xxxxxxxxxxxxxxx> wrote:
> > Let's do this. How about you throw this way one of the case that would
> > possibly break, and I test it?
>
> Since you make such claims I assume your signalfd() implementation
> considers a signal delivered once it is reported to an epoll() caller.
> Right?

The wakeup phase in epoll does not mean the signal is delivered. That
happens when the caller does a read(2) on the signalfd. The read(2) on the
signalfd ends up in calling dequeue_signal(), the same function use by the
kernel to spill out signals to deliver (they peek from the same queue).



> This is not what you really want, at least not in all cases. A signal
> might be something you want to react on right away. Unless
> pthread_kill() is used it is delivered to the _process_ and not a
> specific thread. But this means if epoll() reports two events to one
> thread calling epoll() (one of them being a signal) and this thread is
> then stuck processing the other request, the signal is not handled
> even though there might be a second or third thread available to
> receive the signal. Those threads have the same right to receive the
> signal and the current implementation always looks for the
> best/fastest way to deliver the signal.

The behaviour depends on the sigmask you pass to signalfd(). You can
select signals that you want to handle in a standard way, and the ones
that you want to handle with signalfd.
Typically programs using signalfd() do not want the asyncronous behaviour
of signals at all (with all the limits you have in the handler), and the
event dispatch loop never blocks by definition (otherwise you have more
serious problems than a signal not delivered). They are also very likely
to be single threaded.



> This means to me that reporting the signal in epoll() does _not_ mark
> the signal as handled. Somehow (probably using the signalfd()
> descriptor) the thread must explicitly request the signal to be
> delivered. But if you do this the epoll() handling is fantastically
> racy if the signal is not blocked.

As I said, when a signal hits send_signal (or the queued versions), a
wakeup is done on the wait queue head poll (or select/epoll) is sleeping
on. This ends up delivring a POLLIN, but the signal is not fetched (by the
mean of dequeue_signal) until a read(2) on the signalfd is done.
Since both standard delivery and signalfd's read(2) fish from the same
queue, you have to block the signals that you want to have the guarantee
to be able to fetch with a read(2) (signalfd supports O_NONBLOCK also).
If you do not block the signal, you get a wakeup, but you may not find a
signal to dequeue at the next read(2), because a standard delivery might
have stole the signal by preceeding you in dequeue_signal.



- Davide


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/