1

I have a Linux process (let's call it the main process) whose standard output is piped to another process (called the downstream process) by means of the shell's pipe operator (|). The main process is set up to receive SIGPIPE signals if the downstream process crashes. Unfortunately, SIGPIPE is not raised until the main process writes to stdout. Is there a way to tell sooner that the downstream process has terminated?

One approach is to write continuously to the downstream process, but that seems wasteful. Another approach is to have a separate watchdog process that monitors all relevant processes, but that is complex. Or perhaps there is some way to use select() to trigger the signal. I am hoping that the main process can do all this itself.

Randall Cook
  • 6,728
  • 6
  • 33
  • 68
  • Is it necessary to know immediately when the downstream process crashes, or would it be enough to know that it has crashed the next time you have something to write to it? – zwol Nov 10 '11 at 03:24
  • As I mention in the question, I'd like to know that the downstream process crashes sooner, rather than on the next write (which might come at an indeterminate time in my context). – Randall Cook Nov 10 '11 at 04:30

2 Answers2

3

It appears the stdout file descriptor becomes "ready for reading" when the receiver crashes:

$ gcc -Wall select-downstream-crash.c -o select-downstream-crash
$ gcc -Wall crash-in-five-seconds.c -o crash-in-five-seconds
$ ./select-downstream-crash | ./crash-in-five-seconds
    ... five seconds pass ...
stdout is ready for reading
Segmentation fault

select-downstream-crash.c

#include <err.h>
#include <stdio.h>
#include <sys/select.h>
#include <unistd.h>

int main(void)
{
    fd_set readfds;
    int rc;

    FD_ZERO(&readfds);
    FD_SET(STDOUT_FILENO, &readfds);

    rc = select(STDOUT_FILENO + 1, &readfds, NULL, NULL, NULL);
    if (rc < 0)
        err(1, "select");

    if (FD_ISSET(STDOUT_FILENO, &readfds))
        fprintf(stderr, "stdout is ready for reading\n");

    return 0;
}

crash-in-five-seconds.c

#include <stdio.h>
#include <unistd.h>

int main(void)
{
    sleep(5);
    putchar(*(char*)NULL);
    return 0;
}

I tried this on Linux, but don't know if it'll work elsewhere. It would be nice to find some documentation explaining this observation.

Joey Adams
  • 41,996
  • 18
  • 86
  • 115
0

If the main process forks the other processes, then it will get SIGCHLD notifications when they exit.

zwol
  • 135,547
  • 38
  • 252
  • 361
  • 1
    Right. Unfortunately, the downstream process is created by the shell and connected by the pipe operator: `main | downstream`. – Randall Cook Nov 10 '11 at 01:30