[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Ignored SIGPIPE with line bufferization (wrapped by 'stdbuf -oL')
From: |
Andrew J. Schorr |
Subject: |
Re: Ignored SIGPIPE with line bufferization (wrapped by 'stdbuf -oL') |
Date: |
Thu, 28 Jul 2022 18:04:06 -0400 |
User-agent: |
Mutt/1.5.21 (2010-09-15) |
Hi,
On Fri, Jul 29, 2022 at 12:56:35AM +0500, Nikita Zlobin wrote:
> There's case, when it ignores SIGPIPE, but that happens only with line
> bufferization (using stdbuf). Disabled bufferization or manual flush
> (no stdbuf used) don't cause such problem.
>
> First reported for gentoo:
> https://bugs.gentoo.org/830705
>
> Besides releases this bug reproduces with git version
> (commit 74fcab9e4307e0d6a85c6e269eed3da276df08a4).
>
> Minimal working example:
> yes | stdbuf -oL gawk '{print}' | head -n1 # Prints but hangs
> yes | stdbuf -o0 gawk '{print}' | head -n1 # OK
> yes | gawk '{print; fflush()}' | head -n1 # OK
>
> head -n1 process usually disappears.
> stdbuf is from coreutils-8.32-r1.
Thanks for the report. This is interesting. Based on some preliminary
investigation, it seems to me that builtin.c:do_print calls efwrite to print
the message, and builtin.c:efwrite calls fwrite to send the caracters to
stdout, and the problem is that fwrite is not reporting any error back to gawk.
So the question is what is stdbuf doing that causes fwrite to return success
despite the fact that it's writing to a broken pipe. This might be a glibc bug.
Or I haven't had enough coffee today.
With this patch, you can see what is happening:
diff --git a/builtin.c b/builtin.c
index 3079540..dae5641 100644
--- a/builtin.c
+++ b/builtin.c
@@ -175,6 +175,8 @@ efwrite(const void *ptr,
wrerror(fp, from, rp);
return;
}
+ else
+ fprintf(stderr, "debug: fwrite successfully wrote %zu bytes
starting with ASCII %d\n", count, (int)*(char *)ptr);
if (flush
&& ((fp == stdout && output_is_tty)
|| (rp != NULL && (rp->flag & RED_NOBUF) != 0)))
I'm seeing:
bash-4.2$ (yes | stdbuf -oL ./gawk '{print}' | head -n1) |& head -n20
debug: fwrite successfully wrote 1 bytes starting with ASCII 121
debug: fwrite successfully wrote 1 bytes starting with ASCII 10
debug: fwrite successfully wrote 1 bytes starting with ASCII 121
debug: fwrite successfully wrote 1 bytes starting with ASCII 10
debug: fwrite successfully wrote 1 bytes starting with ASCII 121
debug: fwrite successfully wrote 1 bytes starting with ASCII 10
debug: fwrite successfully wrote 1 bytes starting with ASCII 121
debug: fwrite successfully wrote 1 bytes starting with ASCII 10
debug: fwrite successfully wrote 1 bytes starting with ASCII 121
debug: fwrite successfully wrote 1 bytes starting with ASCII 10
debug: fwrite successfully wrote 1 bytes starting with ASCII 121
debug: fwrite successfully wrote 1 bytes starting with ASCII 10
debug: fwrite successfully wrote 1 bytes starting with ASCII 121
debug: fwrite successfully wrote 1 bytes starting with ASCII 10
debug: fwrite successfully wrote 1 bytes starting with ASCII 121
debug: fwrite successfully wrote 1 bytes starting with ASCII 10
debug: fwrite successfully wrote 1 bytes starting with ASCII 121
debug: fwrite successfully wrote 1 bytes starting with ASCII 10
debug: fwrite successfully wrote 1 bytes starting with ASCII 121
debug: fwrite successfully wrote 1 bytes starting with ASCII 10
If you run with strace, you see that write starts to return -1 with EPIPE,
but fwrite continues to indicate success:
bash-4.2$ (yes | stdbuf -oL strace ./gawk '{print}' | head -n1) |& head -n200 |
tail
--- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=9053, si_uid=300} ---
write(2, "debug: fwrite successfully wrote"..., 64debug: fwrite successfully
wrote 1 bytes starting with ASCII 10
) = 64
write(2, "debug: fwrite successfully wrote"..., 65debug: fwrite successfully
wrote 1 bytes starting with ASCII 121
) = 65
write(1, "y\n", 2) = -1 EPIPE (Broken pipe)
--- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=9053, si_uid=300} ---
write(2, "debug: fwrite successfully wrote"..., 64debug: fwrite successfully
wrote 1 bytes starting with ASCII 10
) = 64
write(2, "debug: fwrite successfully wrote"..., 65debug: fwrite successfully
wrote 1 bytes starting with ASCII 121
This is on an old CentOS 7.9 system with glibc 2.17. I haven't tried on a newer
O/S yet.
Regards,
Andy