bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [patch] fix "broken pipe" message from lseek test


From: Ben Pfaff
Subject: Re: [patch] fix "broken pipe" message from lseek test
Date: Sat, 20 Feb 2010 22:11:38 -0800
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux)

Bruno Haible <address@hidden> 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:

    address@hidden:~/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
---------------------------

    address@hidden:~/tmp(0)$ strace -o foo -f bash
    address@hidden:~/tmp(0)$ trap - SIGPIPE
    address@hidden:~/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.

    address@hidden:~/tmp(0)$ echo hi | ./a.out
    bash: echo: write error: Broken pipe
    address@hidden:~/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.

    address@hidden:~/tmp(0)$ strace -o bar -f bash
    address@hidden:~/tmp(0)$ trap '' SIGPIPE
    address@hidden:~/tmp(0)$ grep ^Sig /proc/$$/status
    SigQ:   1/16382
    SigPnd: 0000000000000000
    SigBlk: 0000000000010000
    SigIgn: 0000000000385000
    SigCgt: 000000004b812eff

SigIgn: ...5000 means SIGPIPE is SIG_IGN.

    address@hidden:~/tmp(0)$ echo hi | ./a.out
    bash: echo: write error: Broken pipe
    address@hidden:~/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 <address@hidden>
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  <address@hidden>
+
+       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  <address@hidden>
 
        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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]