This is the mail archive of the
mailing list for the Cygwin project.
pthread_kill: signals remain pending after target thread exits
- From: John Carey <aeolus at electric-cloud dot com>
- To: "cygwin at cygwin dot com" <cygwin at cygwin dot com>
- Date: Fri, 11 Sep 2015 18:11:25 +0000
- Subject: pthread_kill: signals remain pending after target thread exits
- Authentication-results: sourceware.org; auth=none
There seems to be a problem with pthread_kill: a pending signal targeting a particular thread prevents other threads from receiving signals sharing the same signal number--even after the original target thread exits and is joined.
To reproduce the issue:
1. Block signal number S.
2. Create thread T.
3. Send a signal with signal number S to thread T in particular (as opposed to the process in general).
4. After that signal has been sent, allow T to terminate without unblocking S or calling sigwait().
5. Join T.
6. Create thread N.
7. Have N call sigwait() with a signal set that contains S.
8. Send to N a new signal with signal number S.
9. N never receives the new signal--instead, the new signal is discarded because the earlier signal remains pending.
BUT: It seems possible that N might inadvertently inherit the pending signal if its _cygtls instance happens to be allocated at the same address as the _cygtls instance of T. It would be hard to predict when that would happen. See the discussion of the source code, below.
For comparison, note that when performing the same steps on Linux (Ubuntu 14.04.3), N does in fact receive the second signal.
Here is the relevant Cygwin source code, if I am understanding things correctly:
- sigproc.cc : wait_sig : calls pending_signals::add, then tries to process signals in the queue, but leaves queued any signal that failed to process
- exceptions.cc : sigpacket::process : signal processing fails if it cannot find the target thread using init_cygheap::find_tls
- sigproc.cc : pending_signals::add : discards new signals whose signal number matches that of a pending signal--regardless of target thread
- cygheap.cc : init_cygheap::find_tls : looks for a thread by the address of its _cygtls instance, but a thread that has been joined might happen to have had the same _cygtls address as a thread that was subsequently created, and therefore pending signals for terminated threads might sometimes be inherited by unrelated new threads (or so it seems to me--as yet I have not managed to trigger such a scenario)
In my view it would be desirable if:
- Pending signals targeting a particular thread would not outlast that thread.
- Multiple pending signals targeting different threads could coexist, even if they shared the same signal number. This happens on Linux (Ubuntu 14.04.3), where I can generate two signals for two different threads, then sleep for a bit in each target thread, and finally have each thread receive its signal with sigwait()--neither signal is lost during the sleeping period.
-- John Carey
Problem reports: http://cygwin.com/problems.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple