signalfd API issues (was Re: [PATCH/RFC] signal races/bugs, losingTIF_SIGPENDING and other woes)

From: Nicholas Miell
Date: Tue Jun 05 2007 - 21:03:57 EST


On Tue, 2007-06-05 at 17:37 -0700, Davide Libenzi wrote:
> On Tue, 5 Jun 2007, Nicholas Miell wrote:
>
> > On Tue, 2007-06-05 at 17:11 -0700, Davide Libenzi wrote:
> > > On Tue, 5 Jun 2007, Nicholas Miell wrote:
> > >
> > > > Yes, that's certainly wrong, but that's an implementation issue. I was
> > > > more concerned about the design of the API.
> > > >
> > > > Naively, I would expect a reads on a signalfd to return either process
> > > > signals or thread signals targeted towards the thread doing the read.
> > > >
> > > > What it actually does (delivering process signals or thread signals
> > > > targeted towards the thread that created the signalfd) is weird.
> > > >
> > > > For one, it means you can't create a single signalfd, stick it in an
> > > > epoll set, and then wait on that set from multiple threads.
> > >
> > > In your box threads do share the sighand, don't they? :)
> > >
> >
> > I have no idea what you're trying to say, but it doesn't appear to
> > address the issue I raise.
>
> "For one, it means you can't create a single signalfd, stick it in an
> epoll set, and then wait on that set from multiple threads."
>
> Why not?
> A signalfd, like I said, is attached to the sighand, that is shared by the
> threads.
>
>

POSIX requires the following:

"At the time of generation, a determination shall be made whether the
signal has been generated for the process or for a specific thread
within the process. Signals which are generated by some action
attributable to a particular thread, such as a hardware fault, shall be
generated for the thread that caused the signal to be generated. Signals
that are generated in association with a process ID or process group ID
or an asynchronous event, such as terminal activity, shall be generated
for the process."

In practice, this means that signals like SIGSEGV/SIGFPE/SIGILL/etc. and
signals generated by pthread_kill() (i.e. tkill() or tgkill()) are
directed to a specific threads, while other signals are directed to the
process as a whole and serviced by any thread that isn't blocking that
specific signal.

Linux accomplishes this by having two lists of pending signals --
current->pending is the per-thread list and
current->signal->shared_pending is the process-wide list.

dequeue_signal(tsk, ...) looks for signals first in tsk->pending and
then in tsk->signal->shared_pending.

sys_signalfd() stores current in signalfd_ctx. signalfd_read() passes
that context to signalfd_dequeue, which passes that that saved
task_struct pointer to dequeue_signal.

This means that a signalfd will deliver signals targeted towards either
the original thread that created that signalfd, or signals targeted
towards the process as a whole.

This means that a single signalfd is not adequate to handle signal
delivery for all threads in a process, because signals targeted towards
threads other than the thread that originally created the signalfd will
never be queued to that signalfd.

Is my analysis wrong?

--
Nicholas Miell <nmiell@xxxxxxxxxxx>

-
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/