3

There is a daemon which has two threads: th1, th2. th2 reads a socket using read(2).

If I kill the daemon with SIGTERM, th1 catches and handles the signal (sets the termination flag), after that the daemon destructor get called, it calls pthread_kill(th2, SIGTERM). However, the second thread does not receive SIGTERM, so it does not get killed (when the socket receives data and gets out from read(), it finishes execution, as the termination flag has been set).

If I call pthread_kill(th2, SIGUSR2), and then pthread_kill(th2, SIGTERM), everything finishes correctly. Thus, it seems that UNIX doesn't allow sending identical signals consequently.

Does this behaviour depend on operating system? Can we ensure that the specified thread receives SIGTERM from another thread?

vissi
  • 2,325
  • 1
  • 19
  • 26
  • 1
    You'll get more 'eyes' on you question if you include appropriate programming language tags, c, c++, or yourLanguageHere. Good luck. – shellter Aug 03 '11 at 16:11
  • 2
    Thanks, added the tag. I assumed that unix means C ) – vissi Aug 03 '11 at 17:00
  • 2
    @vissi: That's wrong. You should only include the tag of the language in which you are working. Unless your question concerns interoperability, you should only ever tag one language. – Puppy Aug 03 '11 at 18:27
  • Show us the code, please. Does th2 have SIGTERM masked out? Does th1 call pthread_kill from within its own signal handler? Was your TERM handler installed SA_RESTART? Why doesn't USR1 terminate the process -- how are you handling that? – pilcrow Aug 03 '11 at 18:32
  • Also, what do you mean you want to "kill" th2? Do you want merely to interrupt a blocking `read()`? To cancel a running thread? To deliver a specific signal? To kill the whole process? – pilcrow Aug 03 '11 at 20:48

2 Answers2

5

Unix does allow sending multiple consecutive signals to a process, although if the signals are sent too close together, or an additional signal was been sent to the process before an already pending signal was delivered, then multiple signals can be concatenated into a single signal event.

Also keep in mind that while pthread_kill() sends a signal to a given thread to be handled, the actual handling of the signal has a global effect (i.e., signal handlers are per-process, not per-thread).

You may also want to look into explicitly calling pthread_cancel() since read() is a valid cancellation point. You can, if needed, add a cancellation handler, as well as block the cancellation-state of a thread if you are using functions that are not cancellation-safe. You can read some tips on using pthread_cancel() here.

Jason
  • 31,834
  • 7
  • 59
  • 78
  • `sigaction()` and SA_SIGINFO are quite orthogonal to POSIX realtime signal queueing behavior -- it's inaccurate to say they "enable" realtime semantics. Moreover, it's misleading to suggest that those semantics can be enabled at runtime. Realtime signals (SIGRTMIN .. SIGRTMAX) always queue, whereas standard signals do not. (The spec allows them to, but, in practice, they do not.) – pilcrow Aug 03 '11 at 20:47
  • Okay, that's where my confusion arose ... from the specs (rather than as implemented, I'm assuming in Linux), it seemed as though standard signals would also be queued in addition to real-time signals if you used `sigaction()` to set SA_SIGINFO for the standard signal type. Thanks for clarifying this ... I'll update my answer. – Jason Aug 04 '11 at 01:43
1

A relatively old-school but effective approach is to use select() and a pipe to re-dispatch signals to all threads. (You select() on your blocking handle an the pipe read handle).

Joshua
  • 40,822
  • 8
  • 72
  • 132