Re: SIGPIPE propagation




On Sat, 1 Mar 2008, Martin Laabs wrote:

as you probably know I want to expand dump in such a way it enableds multivolume dumps also when the output data is written to stdout/a pipe. Now I ran into a serious problem. Dump counts the written bytes to remember where it has to proceede after the volumen change. Now the SIGPIPE signal does not propagate fast enought through the system. Thus dump writes some time after the pipe has got broken data into the pipe while it doesn't exist anymore. This short time it does not receive any error about that. (Until the signal propagates to dump.) I wrote a small test progam to demonstrate this effect (and get clear about it by myself). It just write data to stdout and counts it until the pipe is broken (and the write call will return -1) This is the output of a few successively runs:

Here's how SIGPIPE works: when one endpoint of a pipe or socketpair is closed, the other endpoint will be flagged to return EPIPE for any further system calls to write to the pipe or socket. The interesting case involves what to do if there is already an in-progress system call for a thread writing to it. There are a few cases from the perspective of an application writer:

(1) The write is issued "before" the close and can be fully satisfied without
sleeping, in which case it returns the number of bytes written.

(2) The write is issued "after" the close and returns EPIPE and/or SIGPIPE
depending on signal disposition, socket options, etc.

(3) The write is issued "during" the close, and in particular, in a case where
the write was blocking waiting on the reader to make more space available
to hold all of the written data. The kernel will return a positive
integer that is potentially smaller than the requested write because it
has written some bytes successfully, and the next write will return EPIPE.

I think you may be tripping over case (3) if you are using blocking I/O on the pipe/socketpair -- some data was written, just not all of it, and the remote close interrupted the write, leading to a success response followed by an asynchronous failure on the next write. SIGPIPE, FYI, is generated in the writer context due to EPIPE coming back from the socket/pipe code, and not generated by the closing of the remote socket endpoint, so SIGPIPE will not be delivered until a write is attempted on a socket with no remote endpoint.

Does this explain the behavior you were seeing?

Robert N M Watson
Computer Laboratory
University of Cambridge



$ ./a.out |asdf
$ asdf: command not found
cought broken pipe
i: 12 could only wrote -1 bytes. total wrote: 61440

$ ./a.out |asdf
$ asdf: command not found
cought broken pipe
i: 1 could only wrote -1 bytes. total wrote: 5120

$ ./a.out |asdf
$ asdf: command not found
cought broken pipe
i: 12 could only wrote -1 bytes. total wrote: 61440

$ ./a.out |asdf
$ asdf: command not found
cought broken pipe
i: 0 could only wrote -1 bytes. total wrote: 0


Dump encounters the same effect and I don't know how
to handle this problem. Do you have any idea how I
can manage this?

Thank you,
Martin L.

PS: Here's the code of the small test-program:

-----------------:<----------------
#include <stdio.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/errno.h>
#include <fcntl.h>
#include <signal.h>

#define MUL 5
char buffer [1024 * MUL];

void
sigpipe(int signo __unused)
{
fprintf(stderr, "cought broken pipe\n");
}

main()
{
int i , w;
int wr = 0;

signal(SIGPIPE, sigpipe);

for (i = 0; i <= 100; i++) {
w = write(STDOUT_FILENO, buffer, MUL * 1024);
if (w > 0)
wr += w;
if (w != 1024 * MUL) {
fprintf(stderr, "i: %d could only wrote %d bytes. total
break;
}
}
}
------------------------:<--------------------------------
_______________________________________________
freebsd-hackers@xxxxxxxxxxx mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@xxxxxxxxxxx"
_______________________________________________
freebsd-hackers@xxxxxxxxxxx mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@xxxxxxxxxxx"



Relevant Pages

  • Re: emulate an end-of-media
    ... I'll write a script that back up my data on dvd-r and dvd-rams. ... Therefore I'd like to use dump. ... I'd like to use some sort of compression. ... close the pipe after the amount of compressed data reached ...
    (freebsd-hackers)
  • SIGPIPE propagation
    ... as you probably know I want to expand dump in such ... output data is written to stdout/a pipe. ... $ asdf: command not found ...
    (freebsd-hackers)
  • emulate an end-of-media
    ... I'll write a script that back up my data on dvd-r and dvd-rams. ... Therefore I'd like to use dump. ... I'd like to use some sort of compression. ... close the pipe after the amount of compressed data reached ...
    (freebsd-hackers)
  • Re: SIGPIPE propagation
    ... as you probably know I want to expand dump in such ... output data is written to stdout/a pipe. ... soon as possible (command does not exist). ...
    (freebsd-hackers)
  • Lamentations
    ... No problem attaching the pipe that brings the clean water to the ... Rubber pipe, circular plastic drain ... Obvious that the rubber hose should go over the plastic teeth, ... electric socket soon as look at it, and change it for one with 4 plug ...
    (uk.rec.sheds)