Broken pipe no longer ends programs?
Asked Answered
E

3

5

When you pipe two process and kill the one at the "output" of the pipe, the first process used to receive the "Broken Pipe" signal, which usually terminated it aswell. E.g. running

$> do_something_intensive | less

and then exiting less used to return you immediately to a responsive shell, on a SuSE8 or former releases. when i'm trying that today, do_something_intensive is obviously still running until i kill it manually. It seems that something has changed (glib ? shell ?) that makes program ignore "broken pipes" ...

Anyone of you has hints on this ? how to restore the former behaviour ? why it has been changed (or why it always existed multiple semantics) ?

edit : further tests (using strace) reveal that "SIGPIPE" is generated, but that the program is not interrupted. A simple

#include <stdio.h>
int main() 
{
   while(1) printf("dumb test\n");
   exit(0);
}

will go on with an endless

--- SIGPIPE (Broken pipe) @ 0 (0) ---
write(1, "dumb test\ndumb test\ndumb test\ndu"..., 1024) = -1 EPIPE (Broken pipe)

when less is killed. I could for sure program a signal handler in my program and ensure it terminates, but i'm more looking for some environment variable or a shell option that would force programs to terminate on SIGPIPE

edit again: it seems to be a tcsh-specific issue (bash handles it properly) and terminal-dependent (Eterm 0.9.4)

Engage answered 19/9, 2008 at 15:39 Comment(2)
It would help to know what shell you are using, and more specifics about what do_something_intensive actually does. Also, what do you mean by "obviously still running"? Does it show up in a ps listing, or is that the shell is unresponsive? Feel free to edit your question with more details!Wingard
it shows up in a PS list, the sheel doesn't respond until i kill the whole chain with CTRL+C and CPU usage gets high in gkrellm. the shell in use is tcsh, as now mentionned in the more-detailed question. thanks for your comment.Engage
E
0

Thanks for your advices, the solution is getting closer...

According to the manpage of tcsh, "non-login shells inherit the terminate behavior from their parents. Other signals have the values which the shell inherited from its parent."

Which suggest my terminal is actually the root of the problem ... if it ignored SIGPIPE, the shell itself will ignore SIGPIPE as well ...

edit: i have the definitive confirmation that the problem only arise with Eterm+tcsh and found a suspiciously missing signal(SIGPIPE,SIG_DFL) in Eterm source code. I think that close the case.

Engage answered 23/9, 2008 at 15:50 Comment(2)
I remember from way back that quitting a csh shell with backgrouynd jobs allowed the jobs to carry on running, but quitting a bash(ksh) shell would kill any non nohup-ed jobs.Essieessinger
eterm/Eterm> svn diff Index: src/command.c =================================================================== --- src/command.c (revision 40503) +++ src/command.c (working copy) @@ -2304,6 +2304,7 @@ signal(SIGILL, SIG_DFL); signal(SIGSYS, SIG_DFL); signal(SIGALRM, SIG_DFL); + signal(SIGPIPE, SIG_DFL); #ifdef SIGTSTP signal(SIGTSTP, SIG_IGN); signal(SIGTTIN, SIG_IGN);Engage
T
8

Well, if there is an attempt to write to a pipe after the reader has gone away, a SIGPIPE signal gets generated. The application has the ability to catch this signal, but if it doesn't, the process is killed.

The SIGPIPE won't be generated until the calling process attempts to write, so if there's no more output, it won't be generated.

Tympanist answered 19/9, 2008 at 15:45 Comment(0)
C
2

Has "do something intensive" changed at all?

As Daniel has mentioned SIGPIPE is not a magic "your pipe went away" signal but rather a "nice try, you can no longer read/write that pipe" signal.

If you have control of "do something intensive" you could change it to write out some "progress indicator" output as it spins. This would raise the SIGPIPE in a timely fashion.

Contrite answered 19/9, 2008 at 16:26 Comment(1)
about do_something_intensive: if i'm doing "yes | less" and terminate 'less', "yes" receives a SIGPIPE and terminates. if instead i'm doing "objdump -drS ... | less", "objdump" goes on (despite strace reveals reapeated SIGPIPEs); so does a dumb loop doing "printf".Engage
E
0

Thanks for your advices, the solution is getting closer...

According to the manpage of tcsh, "non-login shells inherit the terminate behavior from their parents. Other signals have the values which the shell inherited from its parent."

Which suggest my terminal is actually the root of the problem ... if it ignored SIGPIPE, the shell itself will ignore SIGPIPE as well ...

edit: i have the definitive confirmation that the problem only arise with Eterm+tcsh and found a suspiciously missing signal(SIGPIPE,SIG_DFL) in Eterm source code. I think that close the case.

Engage answered 23/9, 2008 at 15:50 Comment(2)
I remember from way back that quitting a csh shell with backgrouynd jobs allowed the jobs to carry on running, but quitting a bash(ksh) shell would kill any non nohup-ed jobs.Essieessinger
eterm/Eterm> svn diff Index: src/command.c =================================================================== --- src/command.c (revision 40503) +++ src/command.c (working copy) @@ -2304,6 +2304,7 @@ signal(SIGILL, SIG_DFL); signal(SIGSYS, SIG_DFL); signal(SIGALRM, SIG_DFL); + signal(SIGPIPE, SIG_DFL); #ifdef SIGTSTP signal(SIGTSTP, SIG_IGN); signal(SIGTTIN, SIG_IGN);Engage

© 2022 - 2024 — McMap. All rights reserved.