Question
Is it possible to disable the raising of a signal (SIGPIPE
) when writing to a pipe()
FD, without installing my own signal handler or disabling/masking the signal globally?
Background
I'm working on a small library that occasionally creates a pipe, and fork()
s a temporary child/dummy process that waits for a message from the parent. When the child process receives the message from the parent, it dies (intentionally).
Problem
The child process, for circumstances beyond my control, runs code from another (third party) library that is prone to crashing, so I can't always be certain that the child process is alive before I write()
to the pipe.
This results in me sometimes attempting to write()
to the pipe with the child process' end already dead/closed, and it raises a SIGPIPE
in the parent process. I'm in a library other customers will be using, so my library must be as self-contained and transparent to the calling application as possible. Installing a custom signal handler could break the customer's code.
Work so far
I've got around this issue with sockets by using setsockopt(..., MSG_NOSIGNAL)
, but I can't find anything functionally equivalent for pipes. I've looked at temporarily installing a signal handler to catch the SIGPIPE
, but I don't see any way to limit its scope to the calling function in my library rather than the entire process (and it's not atomic).
I've also found a similar question here on SO that is asking the same thing, but unfortunately, using poll()
/select()
won't be atomic, and there's the remote (but possible) chance that the child process dies between my select()
and write()
calls.
Question (redux)
Is there any way to accomplish what I'm attempting here, or to atomically check-and-write to a pipe without triggering the behavior that will generate the SIGPIPE
? Additionally, is it possible to achieve this and know if the child process crashed? Knowing if it crashed lets me build a case for the vendor that supplied the "crashy" library, and lets them know how often it's failing.
After going through all the possible ways to tackle this issue, I discovered there were only two venues to tackle this problem:
socketpair(PF_LOCAL, SOCK_STREAM, 0, fd)
, in place of pipes.fork()
which is allowed to crash ifSIGPIPE
is raised.I went the
socketpair
route. I didn't want to, since it involved re-writing a fair bit of pipe logic, but it's wasn't too painful.Thanks!