Subject: bin/30287: progress(1) sometimes dies silently by SIGPIPE
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: None <umezawa@iij.ad.jp>
List: netbsd-bugs
Date: 05/20/2005 09:07:00
>Number:         30287
>Category:       bin
>Synopsis:       progress(1) sometimes dies silently by SIGPIPE
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri May 20 09:07:00 +0000 2005
>Originator:     UMEZAWA Takeshi
>Release:        1.6.2
>Organization:
Internet Initiative Japan
>Environment:
NetBSD idgw07.iij.ad.jp 1.6.2_STABLE NetBSD 1.6.2_STABLE (GENERIC) #0: Mon May  2 11:40:58 JST 2005     root@idgw07.iij.ad.jp:/usr/src/sys/arch/i386/compile/GENERIC i386

>Description:
progress(1) neither ignores nor handles SIGPIPE.

When outpipe[1]'s peer is closed (e.g. spawned "tar" program died) and
write(2) is called, the process which prints progress bar terminates
without any error messages.

I confirmed SIGPIPE with following modifications.

--- /usr/src/usr.bin/progress/progress.c        Mon Jun  2 23:33:57 2003
+++ ./progress.c        Fri May 20 17:56:19 2005
@@ -78,6 +78,11 @@
        exit(1);
 }

+void sig_pipe(int sig)
+{
+       fprintf(stderr, "\nSIGPIPE!!\n");
+       exit(1);
+}

 int
 main(int argc, char *argv[])
@@ -90,6 +95,8 @@
        ssize_t nr, nw, off;
        struct stat statb;
        struct ttysize ts;
+
+       signal(SIGPIPE, sig_pipe);

        setprogname(argv[0]);


>How-To-Repeat:
do
  progress -zf some.tgz tar xpf - || echo "failed."
many times.

progress(1) failes *rarely* and "failed." is printed by echo(1).
But progress(1) itself does not prints any error messages.
>Fix:
A patch follows. It simply ignores SIGPIPE.
Errors are detected by return value of write(2) and errno(2), which are already implemented in progress(1).

--- /usr/src/usr.bin/progress/progress.c        Mon Jun  2 23:33:57 2003
+++ ./progress.c        Fri May 20 18:02:52 2005
@@ -91,6 +91,8 @@
        struct stat statb;
        struct ttysize ts;

+       signal(SIGPIPE, SIG_IGN);
+
        setprogname(argv[0]);

        /* defaults: Read from stdin, 0 filesize (no completion estimate) */