Under what conditions exactly does SIGPIPE happen?

Clash Royale CLAN TAG#URR8PPP
up vote
2
down vote
favorite
Say we have a named pipe called fifo, and we're reading and writing to it from two different shells. Consider these two examples:
shell 1$ echo foo > fifo
<hangs>
shell 2$ cat fifo
foo
shell 1$ echo bar > fifo
<hangs>
shell 1$ cat > fifo
<typing> foo
<hangs>
shell 2$ cat fifo
foo
^C
shell 1$
<typing> bar
<exits>
I can't wrap my head around what happens in these examples, and in particular why trying to write 'bar' to the pipe in the first example results in a blocking call, whereas in the second example it triggers a SIGPIPE.
I do understand that in the first case, two separate processes write to the pipe, and thus it is opened twice, while in the second case it is only opened once by a single process and written to twice, with the process reading from the pipe being killed in the meantime. What I don't understand is how that affects the behaviour of write.
The pipe(7) man page states:
If all file descriptors referring to the read end of a pipe have been closed, then a write(2) will cause a SIGPIPE signal to be generated for the calling process.
This condition doesn't sound clear to me. A closed file descriptor just ceases to be a file descriptor, right? How does saying "the reading end of the pipe has been closed" differ from "the reading end of the pipe is not open"?
I hope my question was clear enough. By the way, if you could suggest pointers for understanding in details the functioning of Unix pipes in relationship to open, close, read and write operations, I'd greatly appreciate it.
pipe signals fifo read-write
add a comment |Â
up vote
2
down vote
favorite
Say we have a named pipe called fifo, and we're reading and writing to it from two different shells. Consider these two examples:
shell 1$ echo foo > fifo
<hangs>
shell 2$ cat fifo
foo
shell 1$ echo bar > fifo
<hangs>
shell 1$ cat > fifo
<typing> foo
<hangs>
shell 2$ cat fifo
foo
^C
shell 1$
<typing> bar
<exits>
I can't wrap my head around what happens in these examples, and in particular why trying to write 'bar' to the pipe in the first example results in a blocking call, whereas in the second example it triggers a SIGPIPE.
I do understand that in the first case, two separate processes write to the pipe, and thus it is opened twice, while in the second case it is only opened once by a single process and written to twice, with the process reading from the pipe being killed in the meantime. What I don't understand is how that affects the behaviour of write.
The pipe(7) man page states:
If all file descriptors referring to the read end of a pipe have been closed, then a write(2) will cause a SIGPIPE signal to be generated for the calling process.
This condition doesn't sound clear to me. A closed file descriptor just ceases to be a file descriptor, right? How does saying "the reading end of the pipe has been closed" differ from "the reading end of the pipe is not open"?
I hope my question was clear enough. By the way, if you could suggest pointers for understanding in details the functioning of Unix pipes in relationship to open, close, read and write operations, I'd greatly appreciate it.
pipe signals fifo read-write
add a comment |Â
up vote
2
down vote
favorite
up vote
2
down vote
favorite
Say we have a named pipe called fifo, and we're reading and writing to it from two different shells. Consider these two examples:
shell 1$ echo foo > fifo
<hangs>
shell 2$ cat fifo
foo
shell 1$ echo bar > fifo
<hangs>
shell 1$ cat > fifo
<typing> foo
<hangs>
shell 2$ cat fifo
foo
^C
shell 1$
<typing> bar
<exits>
I can't wrap my head around what happens in these examples, and in particular why trying to write 'bar' to the pipe in the first example results in a blocking call, whereas in the second example it triggers a SIGPIPE.
I do understand that in the first case, two separate processes write to the pipe, and thus it is opened twice, while in the second case it is only opened once by a single process and written to twice, with the process reading from the pipe being killed in the meantime. What I don't understand is how that affects the behaviour of write.
The pipe(7) man page states:
If all file descriptors referring to the read end of a pipe have been closed, then a write(2) will cause a SIGPIPE signal to be generated for the calling process.
This condition doesn't sound clear to me. A closed file descriptor just ceases to be a file descriptor, right? How does saying "the reading end of the pipe has been closed" differ from "the reading end of the pipe is not open"?
I hope my question was clear enough. By the way, if you could suggest pointers for understanding in details the functioning of Unix pipes in relationship to open, close, read and write operations, I'd greatly appreciate it.
pipe signals fifo read-write
Say we have a named pipe called fifo, and we're reading and writing to it from two different shells. Consider these two examples:
shell 1$ echo foo > fifo
<hangs>
shell 2$ cat fifo
foo
shell 1$ echo bar > fifo
<hangs>
shell 1$ cat > fifo
<typing> foo
<hangs>
shell 2$ cat fifo
foo
^C
shell 1$
<typing> bar
<exits>
I can't wrap my head around what happens in these examples, and in particular why trying to write 'bar' to the pipe in the first example results in a blocking call, whereas in the second example it triggers a SIGPIPE.
I do understand that in the first case, two separate processes write to the pipe, and thus it is opened twice, while in the second case it is only opened once by a single process and written to twice, with the process reading from the pipe being killed in the meantime. What I don't understand is how that affects the behaviour of write.
The pipe(7) man page states:
If all file descriptors referring to the read end of a pipe have been closed, then a write(2) will cause a SIGPIPE signal to be generated for the calling process.
This condition doesn't sound clear to me. A closed file descriptor just ceases to be a file descriptor, right? How does saying "the reading end of the pipe has been closed" differ from "the reading end of the pipe is not open"?
I hope my question was clear enough. By the way, if you could suggest pointers for understanding in details the functioning of Unix pipes in relationship to open, close, read and write operations, I'd greatly appreciate it.
pipe signals fifo read-write
asked Mar 24 at 23:53
Naïm Favier
235
235
add a comment |Â
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
5
down vote
accepted
Your example is using a fifo not a pipe, so is subject to fifo(7). pipe(7) also tells:
A FIFO (short for First In First Out) has a name within the
filesystem (created using mkfifo(3)), and is opened using open(2).
Any process may open a FIFO, assuming the file permissions allow it.
The read end is opened using the O_RDONLY flag; the write end is
opened using the O_WRONLY flag. See fifo(7) for further details.
Note: although FIFOs have a pathname in the filesystem, I/O on FIFOs
does not involve operations on the underlying device (if there is
one).
I/O on pipes and FIFOs
The only difference between pipes and FIFOs is the manner in which
they are created and opened. Once these tasks have been
accomplished, I/O on pipes and FIFOs has exactly the same semantics.
So now from fifo(7):
The kernel maintains exactly one pipe object for each FIFO special
file that is opened by at least one process. The FIFO must be opened
on both ends (reading and writing) before data can be passed.
Normally, opening the FIFO blocks until the other end is opened also.
So before both ends (here meaning there is at least a reader and a writer) are opened, write blocks as per fifo(7). After both ends have been opened, and then (the) reading end(s) closed, write generates SIGPIPE as per pipe(7).
For an example of pipe usage (not fifo) look at the example section of pipe(2) : involves pipe() (no open(), since pipe() actually created the pipe pair opened), close(), read() write() and fork() (there's almost always a fork() around when using a pipe).
The simpliest way to handle SIGPIPE from your own C code if you don't want it to die when writing to a fifo, would be to call signal(SIGPIPE, SIG_IGN); and handle it by checking for errno EPIPE after each write() instead.
add a comment |Â
up vote
0
down vote
Writing to a pipe or FIFO that doesn't have a reading process is treated as an error condition; it generates a SIGPIPE signal, and fails with error code EPIPE if the signal is handled or blocked.
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
5
down vote
accepted
Your example is using a fifo not a pipe, so is subject to fifo(7). pipe(7) also tells:
A FIFO (short for First In First Out) has a name within the
filesystem (created using mkfifo(3)), and is opened using open(2).
Any process may open a FIFO, assuming the file permissions allow it.
The read end is opened using the O_RDONLY flag; the write end is
opened using the O_WRONLY flag. See fifo(7) for further details.
Note: although FIFOs have a pathname in the filesystem, I/O on FIFOs
does not involve operations on the underlying device (if there is
one).
I/O on pipes and FIFOs
The only difference between pipes and FIFOs is the manner in which
they are created and opened. Once these tasks have been
accomplished, I/O on pipes and FIFOs has exactly the same semantics.
So now from fifo(7):
The kernel maintains exactly one pipe object for each FIFO special
file that is opened by at least one process. The FIFO must be opened
on both ends (reading and writing) before data can be passed.
Normally, opening the FIFO blocks until the other end is opened also.
So before both ends (here meaning there is at least a reader and a writer) are opened, write blocks as per fifo(7). After both ends have been opened, and then (the) reading end(s) closed, write generates SIGPIPE as per pipe(7).
For an example of pipe usage (not fifo) look at the example section of pipe(2) : involves pipe() (no open(), since pipe() actually created the pipe pair opened), close(), read() write() and fork() (there's almost always a fork() around when using a pipe).
The simpliest way to handle SIGPIPE from your own C code if you don't want it to die when writing to a fifo, would be to call signal(SIGPIPE, SIG_IGN); and handle it by checking for errno EPIPE after each write() instead.
add a comment |Â
up vote
5
down vote
accepted
Your example is using a fifo not a pipe, so is subject to fifo(7). pipe(7) also tells:
A FIFO (short for First In First Out) has a name within the
filesystem (created using mkfifo(3)), and is opened using open(2).
Any process may open a FIFO, assuming the file permissions allow it.
The read end is opened using the O_RDONLY flag; the write end is
opened using the O_WRONLY flag. See fifo(7) for further details.
Note: although FIFOs have a pathname in the filesystem, I/O on FIFOs
does not involve operations on the underlying device (if there is
one).
I/O on pipes and FIFOs
The only difference between pipes and FIFOs is the manner in which
they are created and opened. Once these tasks have been
accomplished, I/O on pipes and FIFOs has exactly the same semantics.
So now from fifo(7):
The kernel maintains exactly one pipe object for each FIFO special
file that is opened by at least one process. The FIFO must be opened
on both ends (reading and writing) before data can be passed.
Normally, opening the FIFO blocks until the other end is opened also.
So before both ends (here meaning there is at least a reader and a writer) are opened, write blocks as per fifo(7). After both ends have been opened, and then (the) reading end(s) closed, write generates SIGPIPE as per pipe(7).
For an example of pipe usage (not fifo) look at the example section of pipe(2) : involves pipe() (no open(), since pipe() actually created the pipe pair opened), close(), read() write() and fork() (there's almost always a fork() around when using a pipe).
The simpliest way to handle SIGPIPE from your own C code if you don't want it to die when writing to a fifo, would be to call signal(SIGPIPE, SIG_IGN); and handle it by checking for errno EPIPE after each write() instead.
add a comment |Â
up vote
5
down vote
accepted
up vote
5
down vote
accepted
Your example is using a fifo not a pipe, so is subject to fifo(7). pipe(7) also tells:
A FIFO (short for First In First Out) has a name within the
filesystem (created using mkfifo(3)), and is opened using open(2).
Any process may open a FIFO, assuming the file permissions allow it.
The read end is opened using the O_RDONLY flag; the write end is
opened using the O_WRONLY flag. See fifo(7) for further details.
Note: although FIFOs have a pathname in the filesystem, I/O on FIFOs
does not involve operations on the underlying device (if there is
one).
I/O on pipes and FIFOs
The only difference between pipes and FIFOs is the manner in which
they are created and opened. Once these tasks have been
accomplished, I/O on pipes and FIFOs has exactly the same semantics.
So now from fifo(7):
The kernel maintains exactly one pipe object for each FIFO special
file that is opened by at least one process. The FIFO must be opened
on both ends (reading and writing) before data can be passed.
Normally, opening the FIFO blocks until the other end is opened also.
So before both ends (here meaning there is at least a reader and a writer) are opened, write blocks as per fifo(7). After both ends have been opened, and then (the) reading end(s) closed, write generates SIGPIPE as per pipe(7).
For an example of pipe usage (not fifo) look at the example section of pipe(2) : involves pipe() (no open(), since pipe() actually created the pipe pair opened), close(), read() write() and fork() (there's almost always a fork() around when using a pipe).
The simpliest way to handle SIGPIPE from your own C code if you don't want it to die when writing to a fifo, would be to call signal(SIGPIPE, SIG_IGN); and handle it by checking for errno EPIPE after each write() instead.
Your example is using a fifo not a pipe, so is subject to fifo(7). pipe(7) also tells:
A FIFO (short for First In First Out) has a name within the
filesystem (created using mkfifo(3)), and is opened using open(2).
Any process may open a FIFO, assuming the file permissions allow it.
The read end is opened using the O_RDONLY flag; the write end is
opened using the O_WRONLY flag. See fifo(7) for further details.
Note: although FIFOs have a pathname in the filesystem, I/O on FIFOs
does not involve operations on the underlying device (if there is
one).
I/O on pipes and FIFOs
The only difference between pipes and FIFOs is the manner in which
they are created and opened. Once these tasks have been
accomplished, I/O on pipes and FIFOs has exactly the same semantics.
So now from fifo(7):
The kernel maintains exactly one pipe object for each FIFO special
file that is opened by at least one process. The FIFO must be opened
on both ends (reading and writing) before data can be passed.
Normally, opening the FIFO blocks until the other end is opened also.
So before both ends (here meaning there is at least a reader and a writer) are opened, write blocks as per fifo(7). After both ends have been opened, and then (the) reading end(s) closed, write generates SIGPIPE as per pipe(7).
For an example of pipe usage (not fifo) look at the example section of pipe(2) : involves pipe() (no open(), since pipe() actually created the pipe pair opened), close(), read() write() and fork() (there's almost always a fork() around when using a pipe).
The simpliest way to handle SIGPIPE from your own C code if you don't want it to die when writing to a fifo, would be to call signal(SIGPIPE, SIG_IGN); and handle it by checking for errno EPIPE after each write() instead.
edited Mar 25 at 1:55
answered Mar 25 at 0:51
A.B
2,5651315
2,5651315
add a comment |Â
add a comment |Â
up vote
0
down vote
Writing to a pipe or FIFO that doesn't have a reading process is treated as an error condition; it generates a SIGPIPE signal, and fails with error code EPIPE if the signal is handled or blocked.
add a comment |Â
up vote
0
down vote
Writing to a pipe or FIFO that doesn't have a reading process is treated as an error condition; it generates a SIGPIPE signal, and fails with error code EPIPE if the signal is handled or blocked.
add a comment |Â
up vote
0
down vote
up vote
0
down vote
Writing to a pipe or FIFO that doesn't have a reading process is treated as an error condition; it generates a SIGPIPE signal, and fails with error code EPIPE if the signal is handled or blocked.
Writing to a pipe or FIFO that doesn't have a reading process is treated as an error condition; it generates a SIGPIPE signal, and fails with error code EPIPE if the signal is handled or blocked.
answered Mar 25 at 11:02
Mumtaz Ahmad
62
62
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f433345%2funder-what-conditions-exactly-does-sigpipe-happen%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password