Bruno Haible <br...@clisp.org> writes: > Ben Pfaff wrote: >> I still see the "broken pipe" error with it. > > Could you please investigate, by using strace, looking at signal masks of > processes, etc.? This "broken pipe" issue in bash is becoming extremely > unsatisfying. We have the world-class shell programming experts on this > mailing list and *still* don't understand how SIGPIPE works?!
I took a closer look, as you asked: b...@blp:~/tmp(0)$ bash --version GNU bash, version 3.2.48(1)-release (i486-pc-linux-gnu) Copyright (C) 2007 Free Software Foundation, Inc. Default handling of SIGPIPE --------------------------- b...@blp:~/tmp(0)$ strace -o foo -f bash b...@blp:~/tmp(0)$ trap - SIGPIPE b...@blp:~/tmp(0)$ grep ^Sig /proc/$$/status SigQ: 1/16382 SigPnd: 0000000000000000 SigBlk: 0000000000010000 SigIgn: 0000000000384000 SigCgt: 000000004b813eff SigIgn: ...4000 means SIGPIPE is not SIG_IGN. SigCgt: ...3eff means SIGPIPE has a registered handler. b...@blp:~/tmp(0)$ echo hi | ./a.out bash: echo: write error: Broken pipe b...@blp:~/tmp(1)$ exit So, "foo" shows what happened: 21287 write(1, "hi\n", 3) = -1 EPIPE (Broken pipe) 21287 --- SIGPIPE (Broken pipe) @ 0 (0) --- 21287 sigreturn() = ? (mask now []) 21287 write(2, "bash: echo: write error: Broken "..., 37) = 37 21287 exit_group(1) = ? bash caught the signal, returned from the handler (returning EPIPE from the write call, I guess), printed the error message, and exited. Ignoring SIGPIPE ---------------- This seems interesting at least for completeness. b...@blp:~/tmp(0)$ strace -o bar -f bash b...@blp:~/tmp(0)$ trap '' SIGPIPE b...@blp:~/tmp(0)$ grep ^Sig /proc/$$/status SigQ: 1/16382 SigPnd: 0000000000000000 SigBlk: 0000000000010000 SigIgn: 0000000000385000 SigCgt: 000000004b812eff SigIgn: ...5000 means SIGPIPE is SIG_IGN. b...@blp:~/tmp(0)$ echo hi | ./a.out bash: echo: write error: Broken pipe b...@blp:~/tmp(1)$ exit This time "bar" shows what happened: 21313 rt_sigaction(SIGPIPE, {0x1, [], 0}, {0x1, [], 0}, 8) = 0 0x1 is SIG_IGN. 21313 rt_sigaction(SIGTERM, {SIG_DFL, [], 0}, {0x1, [], 0}, 8) = 0 21313 rt_sigaction(SIGCHLD, {SIG_DFL, [], 0}, {0x807f600, [], 0}, 8) = 0 21313 pipe([3, 4]) = 0 21313 close(3) = 0 21313 close(4) = 0 21313 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0 21313 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 21313 rt_sigaction(SIGCHLD, {0x807f600, [], 0}, {SIG_DFL, [], 0}, 8) = 0 21313 rt_sigaction(SIGINT, {0x8094050, [], 0}, {SIG_DFL, [], 0}, 8) = 0 21313 rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0 21313 write(1, "hi\n", 3) = -1 EPIPE (Broken pipe) 21313 --- SIGPIPE (Broken pipe) @ 0 (0) --- (The SIGPIPE never gets to the process--it was ignored--but ptrace() and hence strace reports it anyway. You can tell that bash didn't receive it in this case because the log shows no call to sigreturn().) 21313 write(2, "bash: echo: write error: Broken "..., 37) = 37 21313 exit_group(1) = ? So in this case bash just gets the EPIPE directly, prints the error message, and exits. Conclusion ---------- I don't see a way to avoid this with using "echo" in bash 3.2. Your gnulib-tool comment refers to Chet Ramey's email at http://lists.gnu.org/archive/html/bug-bash/2008-12/msg00050.html. I think that he is saying the same thing, actually: The second is that the echo builtin in bash-3.2 displays a message on a write error, instead of letting the exit status communicate the error. When the shell receives SIGPIPE and handles it without exiting, writes to that pipe return -1/EPIPE, and the echo builtin reports the error. In earlier versions, you wouldn't have seen the message. The bash 3.2 "printf" builtin doesn't have this problem though. So, here's a new proposed patch. It does fix the problem for me. commit 7357b5f06c00889037edfc433f1601cba42ba22c Author: Ben Pfaff <b...@cs.stanford.edu> Date: Sat Feb 20 22:09:58 2010 -0800 Avoid "broken pipe" message from lseek test. * m4/lseek.m4: Use "printf" instead of "echo" to avoid "Broken pipe" message from bash 3.2 "echo" builtin. diff --git a/ChangeLog b/ChangeLog index 9d3367e..a6c86b5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2010-02-20 Ben Pfaff <b...@cs.stanford.edu> + + Avoid "broken pipe" message from lseek test. + * m4/lseek.m4: Use "printf" instead of "echo" to avoid "Broken + pipe" message from bash 3.2 "echo" builtin. + 2010-02-19 Bruno Haible <br...@clisp.org> Make it easier to find modules. New gnulib-tool option '--find'. diff --git a/m4/lseek.m4 b/m4/lseek.m4 index f308495..39bbd64 100644 --- a/m4/lseek.m4 +++ b/m4/lseek.m4 @@ -1,4 +1,4 @@ -# lseek.m4 serial 4 +# lseek.m4 serial 5 dnl Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -21,7 +21,7 @@ int main () }], [if test -s conftest$ac_exeext \ && ./conftest$ac_exeext < conftest.$ac_ext \ - && { echo hi | ./conftest$ac_exeext; test $? = 1; }; then + && { printf hi | ./conftest$ac_exeext; test $? = 1; }; then gl_cv_func_lseek_pipe=yes else gl_cv_func_lseek_pipe=no -- Ben Pfaff http://benpfaff.org