If a send cause a SIGPIPE signal, which thead would handle it ? The thread which send or a random thread? In other words, the Linux system send the signal by kill or pthread_kill?
2 Answers
Asynchronous signals like SIGPIPE
can go to any thread. You can use signal masks to limit which of the threads is eligible.
Synchronous signals like SIGSEGV
will be delivered on the thread that caused them.

- 90,079
- 9
- 98
- 150
Summary
The answer to this question has two facets: How the system in question should behave and how it actually behaves.
Since most programmers expect Linux to be mostly POSIX-compatible, we can look into that standard, which actually unambiguously specifies the behavior – the signal is sent directly to the thread which did the write. But whether Linux adheres to it is unclear and Linux documentation is not helpful here. An examination of Linux behavior suggests it conforms to POSIX, but doesn't prove it, and a reading of the source gives us the necessary proof about the current version of Linux.
tl;dr: It is always handled by the thread that did the write.
POSIX Standard
The POSIX standard mandates (since IEEE Std. 1003.1-2001/Cor 2-2004) that SIGPIPE generated as a result of write to a pipe with no readers be delivered to the thread doing the write. See EPIPE in the ERRORS section of the description of write() (emphasis mine):
[EPIPE] An attempt is made to write to a pipe or FIFO that is not open for reading by any process, or that only has one end open. A SIGPIPE signal shall also be sent to the thread.
Linux documentation
That said, it is not clear whether Linux handles this correctly. The page man 7 signal
doesn't give concrete lists of thread- and process-directed signals, just examples, and its definition of thread-directed signals doesn't include SIGPIPE:
A signal may be thread-directed because it was generated as a consequence of executing a specific machine-language instruction that triggered a hardware exception […]
SIGPIPE is not a result of a specific instruction, nor is it triggered by a hardware exception.
Glibc documentation doesn't discuss kernel-generated synchronous thread-directed signals at all (i.e. not even SIGSEGV or SIGBUS are discussed as being thread-directed), and there are years-old reports of bugs in NPTL, although these may have been fixed in the meantime.
Observable Linux behavior
I wrote a program which spawns a thread, which blocks SIGPIPE using pthread_sigmask
, creates a pipe pair, closes the read end and writes a byte into the write end. If the signal is thread-directed, nothing should happen until the signal is unblocked again. If the signal is process-directed, the main thread should handle the signal and the process should die. The reason for this again comes from POSIX: If there is a thread which has the (process-directed) signal unblocked, it should be delivered there instead of queueing:
Signals generated for the process shall be delivered to exactly one of those threads within the process which […] has not blocked delivery of the signal. If […] all threads within the process block delivery of the signal, the signal shall remain pending on the process until […] a thread unblocks delivery of the signal, or the action associated with the signal is set to ignore the signal.
My experimentation suggests that on modern (2020) Linux with recent Glibc the signal is indeed directed to the thread which did the write, because blocking it with pthread_sigmask in the writing thread prevents SIGPIPE from being delivered until it's unblocked.
Linux 5.4.28 source
The behavior observed above doesn't prove anything, because it is entirely possible that Linux simply violates POSIX in several places and the signal delivery depends on some factors I didn't take into account. To get the proof we seek, we can read the source. Of course, this only tells us about the current behavior, not about the intended one – but if we find the current behavior to be POSIX-conforming, it is probably here to stay.
Disclaimer: I'm not a kernel hacker and the following is a result of a cursory reading of the sources. I might have missed something important.
In kernel/signal.c
, there is a SYNCHRONOUS_MASK listing the synchronous signals which are handled specially. These are SIGSEGV, SIGBUS, SIGILL, SIGTRAP, SIGFPE and SIGSYS – SIGPIPE is not in the list. However, that doesn't answer the question – it can be thread-directed without being synchronous.
So how is SIGPIPE sent? It originates from pipe_write()
in fs/pipe.c
, which calls send_sig()
on task_struct current
. The use of current
already hints that the signal is thread-directed, but let's press on. The send_sig()
function is defined in kernel/signal.c
and through some indirection ultimately calls __send_signal()
with pid_type type = PIDTYPE_PID
.
In Linux terminology, PID refers to a single thread. And sure enough, with those parameters, the pending signal list is the thread-specific one, not the shared one; and complete_signal()
(called at the end of the function) doesn't even try to find a thread to wake up, it just returns because the thread has already been chosen. I don't fully understand how the signal queues work, but it seems that the queue is per-thread and so the current thread is the one that gets the signal.

- 11
- 1
- 3