Check for a broken pipe before trying to write to it? [duplicate]
Asked Answered
L

3

5

Is it possible to check if a pipe is broken before trying to write/read to it, so I can just skip it and continue with the program?

I'm utilizing a while loop to write to pipes communicating from the Parent to multiple Children. Over the course of the loop, several of the children will close. When the loop comes around and tries to write to them again, my program shuts down because it is killed by SIGPIPE since the pipe is broken. I know the pipe is broken, I programmed the children to close their pipes and exit (necessary). I still want to finish the loop and move on with the program. I'd like it to check if the pipe is broken, skip over it if broken (without an error output), and move on with the program (the other children still need to be written to).

So, is it possible? An example in c would be great.

Here's a simple pseudocode representation of what I'm asking:

int i = 0;

while(i != 5)
{
    if (mypipe[WRITE] is BROKEN)
        //Do Nothing ---Basically Skip

    else if (some condition)
        write(mypipe[WRITE]);

    i++;
}

This question is related to a previous post of mine, though the context of my question is different. You can review the code for the actual program there.

Lavalley answered 14/10, 2014 at 13:45 Comment(2)
I think there are some thread utilizationions in pthreads that could help.Amorphism
As a workaround, the children could notify the parent (via the pipe ?) that they are done, and it would be the parent responsibility to close the pipes.Pastoralize
I
5

my program shuts down because it is killed by SIGPIPE

You can change that behavior if you install a signal handler that ignores SIGPIPE, that way the write() call to the pipe returns an error instead of killing your program:

  signal(SIGPIPE, SIG_IGN);

Then you simple check

ssize_t rc;
rc = write(...);
if (rc == -1) {
    if (errno == EPIPE) {
         //it's broken
    }
 //some other error occured.
}
Irade answered 14/10, 2014 at 14:9 Comment(1)
That pretty much fixed it. With the following tweek: if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { //Do Nothing } Now my code passes by the broken pipes. Thanks!Lavalley
M
5

You can set up a signal handler to ignore SIGPIPE, and then write to the buffer and check the error code:

/* initialization */
signal(SIGPIPE, SIG_IGN);
...

/* try writing to pipe and detect broken pipe */
ssize_t written = write(mypipe[WRITE], buf, size);
if (written == -1 && errno == EPIPE)
  ... remove pipe from the list and continue processing
Mezzorelievo answered 14/10, 2014 at 14:10 Comment(0)
B
3

Yes, you can use a multiplexing syscall like poll(2) before reading and writing. This will tell you which file descriptors are readable (have something to read) and writable (can be subject of write), amongst a sequence of file descriptors to check for readability or writability.

(You could use the older select(2) multiplexing syscall, but I prefer poll because of the C10K problem)

Beware that some other thread might do something before your own thread.

You want some event loop. See also this answer to a related question.

Burnard answered 14/10, 2014 at 14:6 Comment(1)
Unfortunately the pipe can still close between poll() and write().Oddball

© 2022 - 2024 — McMap. All rights reserved.