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
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

Reply via email to