[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [patch] fix "broken pipe" message from lseek test
From: |
Bruno Haible |
Subject: |
Re: [patch] fix "broken pipe" message from lseek test |
Date: |
Sun, 21 Feb 2010 13:33:47 +0100 |
User-agent: |
KMail/1.9.9 |
Hi Ben,
Thanks for this analysis.
> 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
An even easier way to reproduce it is to run
$ echo hi | true
10 times at a bash prompt. In bash 3.2, it frequently prints the
error message.
> 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.
Aha! So it's really a bug in the 'echo' built-in, and using 'printf' is a
work-around.
I'm updating gnulib-tool: The function func_reset_sigpipe had no effect, since
the bash bug occurs also in the _default_ situation (no inherited trap or
ignored
signal). Also the comment "When "trap '' SIGPIPE" is in effect, the behaviour
(at least with bash) is to terminate the current process with an error message."
was wrong, because it applies only to the 'echo' built-in, not to other
built-ins.
2010-02-21 Bruno Haible <address@hidden>
Really work around around "broken pipe" error message from bash 3.2.
* gnulib-tool (func_reset_sigpipe): Remove function.
(echo): In bash 3.2, define to a function that uses printf.
Analyzed by Ralf Wildenhues, Chet Ramey, Ben Pfaff.
--- gnulib-tool.orig Sun Feb 21 13:24:10 2010
+++ gnulib-tool Sun Feb 21 13:20:19 2010
@@ -661,39 +661,20 @@
fi
}
-# func_reset_sigpipe
-# Resets SIGPIPE to its default behaviour. SIGPIPE is signalled when a process
-# writes into a pipe with no readers, i.e. a pipe where all readers have
-# already closed their file descriptor that read from it or exited entirely.
-# The default behaviour is to terminate the current process without an error
-# message.
-# When "trap '' SIGPIPE" is in effect, the behaviour (at least with bash) is to
-# terminate the current process with an error message.
-# This function should be called at the beginning of a command that only
-# produces output to stdout (i.e. no side effects!), when the command that
-# will read from this pipe might prematurely exit or close its standard input
-# descriptor.
-if test -n "$BASH_VERSION"; then
- # The problem has only been reported with bash. Probably it occurs only with
- # bash-3.2. For the reasons, see
- # <http://lists.gnu.org/archive/html/bug-bash/2008-12/msg00050.html>.
- # Note that Solaris sh does not understand "trap - SIGPIPE".
- func_reset_sigpipe ()
- {
- trap - SIGPIPE
- }
-else
- func_reset_sigpipe ()
- {
- :
- }
-fi
-
-# Ensure an 'echo' command that does not interpret backslashes.
-# Test cases:
+# Ensure an 'echo' command that
+# 1. does not interpret backslashes and
+# 2. does not print an error message "broken pipe" when writing into a pipe
+# with no writers.
+#
+# Test cases for problem 1:
# echo '\n' | wc -l prints 1 when OK, 2 when KO
# echo '\t' | grep t > /dev/null has return code 0 when OK, 1 when KO
-# This problem is a weird heritage from SVR4. BSD got it right (except that
+# Test cases for problem 2:
+# echo hi | true frequently prints
+# "bash: echo: write error: Broken pipe"
+# to standard error in bash 3.2.
+#
+# Problem 1 is a weird heritage from SVR4. BSD got it right (except that
# BSD echo interprets '-n' as an option, which is also not desirable).
# Nowadays the problem occurs in 4 situations:
# - in bash, when the shell option xpg_echo is set (bash >= 2.04)
@@ -716,6 +697,12 @@
# - otherwise: respawn using /bin/sh and rely on the workarounds.
# When respawning, we pass --no-reexec as first argument, so as to avoid
# turning this script into a fork bomb in unlucky situations.
+#
+# Problem 2 is specific to bash 3.2 and affects the 'echo' built-in, but not
+# the 'printf' built-in. See
+# <http://lists.gnu.org/archive/html/bug-bash/2008-12/msg00050.html>
+# <http://lists.gnu.org/archive/html/bug-gnulib/2010-02/msg00154.html>
+# The workaround is: define echo to a function that uses the printf built-in.
have_echo=
if echo '\t' | grep t > /dev/null; then
have_echo=yes # Lucky!
@@ -823,6 +810,15 @@
exec /bin/sh "$0" --no-reexec "$@"
exit 127
fi
+# Now handle problem 2, specific to bash 3.2.
+case "$BASH_VERSION" in
+ 3.2*)
+ echo ()
+ {
+ printf '%s\n' "$*"
+ }
+ ;;
+esac
if test -z "$have_echo"; then
func_fatal_error "Shell does not support 'echo' correctly. Please install
GNU bash and set the environment variable CONFIG_SHELL to point to it."
fi
@@ -2029,8 +2025,7 @@
func_filter_filelist lib_files "$nl" "$all_files" 'lib/' '' 'lib/' ''
# Remove $already_mentioned_files from $lib_files.
echo "$lib_files" | LC_ALL=C sort -u > "$tmp"/lib-files
- extra_files=`func_reset_sigpipe; \
- for f in $already_mentioned_files; do echo $f; done \
+ extra_files=`for f in $already_mentioned_files; do echo $f; done \
| LC_ALL=C sort -u | LC_ALL=C join -v 2 - "$tmp"/lib-files`
if test -n "$extra_files"; then
echo "EXTRA_DIST +=" $extra_files
@@ -2266,7 +2261,7 @@
handledmodules=`for m in $handledmodules $inmodules_this_round; do echo
$m; done | LC_ALL=C sort -u`
# Remove $handledmodules from $inmodules.
for m in $inmodules; do echo $m; done | LC_ALL=C sort -u >
"$tmp"/queued-modules
- inmodules=`func_reset_sigpipe; echo "$handledmodules" | LC_ALL=C join -v 2
- "$tmp"/queued-modules`
+ inmodules=`echo "$handledmodules" | LC_ALL=C join -v 2 -
"$tmp"/queued-modules`
done
modules=`for m in $outmodules; do echo $m; done | LC_ALL=C sort -u`
rm -f "$tmp"/queued-modules
@@ -3354,8 +3349,7 @@
fi
# Determine tests-related module list.
echo "$final_modules" | LC_ALL=C sort -u > "$tmp"/final-modules
- testsrelated_modules=`func_reset_sigpipe
- for module in $main_modules; do
+ testsrelated_modules=`for module in $main_modules; do
if test \`func_get_applicability $module\` = main;
then
echo $module
fi
@@ -4256,8 +4250,7 @@
if test -f "$destdir/$dir$ignore"; then
if test -n "$dir_added" || test -n "$dir_removed"; then
sed -e "s|^$anchor||" < "$destdir/$dir$ignore" | LC_ALL=C sort >
"$tmp"/ignore
- (func_reset_sigpipe
- echo "$dir_added" | sed -e '/^$/d' | LC_ALL=C sort -u \
+ (echo "$dir_added" | sed -e '/^$/d' | LC_ALL=C sort -u \
| LC_ALL=C join -v 1 - "$tmp"/ignore > "$tmp"/ignore-added
echo "$dir_removed" | sed -e '/^$/d' | LC_ALL=C sort -u \
| LC_ALL=C join -v 1 - "$tmp"/ignore > "$tmp"/ignore-removed
- [patch] fix "broken pipe" message from lseek test, Ben Pfaff, 2010/02/20
- Re: [patch] fix "broken pipe" message from lseek test, Bruno Haible, 2010/02/20
- Re: [patch] fix "broken pipe" message from lseek test, Ben Pfaff, 2010/02/20
- Re: [patch] fix "broken pipe" message from lseek test, Eric Blake, 2010/02/20
- Re: [patch] fix "broken pipe" message from lseek test, Bruno Haible, 2010/02/20
- Re: [patch] fix "broken pipe" message from lseek test, Ben Pfaff, 2010/02/21
- Re: [patch] fix "broken pipe" message from lseek test,
Bruno Haible <=
- portability of 'printf' command, Bruno Haible, 2010/02/21
- Re: portability of 'printf' command, Bob Friesenhahn, 2010/02/21
- Re: portability of 'printf' command, Thomas Dickey, 2010/02/22
- Re: portability of 'printf' command, Bob Friesenhahn, 2010/02/21
- Re: portability of 'printf' command, Thomas Dickey, 2010/02/22
- Re: portability of 'printf' command, Ben Pfaff, 2010/02/21
- Re: [patch] fix "broken pipe" message from lseek test, Eric Blake, 2010/02/22