bug-bash
[Top][All Lists]
Advanced

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

Coprocess terminated, pipe closed before I read the data out


From: George
Subject: Coprocess terminated, pipe closed before I read the data out
Date: Wed, 13 Apr 2016 01:13:00 -0400

Configuration Information
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64'
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-pc-linux-gnu'
-DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash'
-DSHELL -DHAVE_CONFIG_H   -I.  -I../. -I.././include -I.././lib  -
D_FORTIFY_SOURCE=2 -g -O2 -fstack-protector-strong -Wformat
-Werror=format-security -Wall
uname output: Linux adamant 4.0.0-2-amd64 #1 SMP Debian 4.0.8-2 (2015-
07-22) x86_64 GNU/Linux
Machine Type: x86_64-pc-linux-gnu

Bash Version: 4.3
Patch Level: 42
Release Status: release


Description:

Coprocess's output pipe is destroyed when coprocess terminates
(possibly before coprocess output has been read)

I realize this is by design, essentially, as Bash's coprocs are meant
to be "self-cleaning" - but in practice I think this is a bad policy,
as variables and file descriptors used by the script are abruptly
removed from the environment.


Repeat-By:

$ coproc head { head -n 10; }
[1] 1864
$ ls >&${head[1]} &
# "head" gets its 10 lines, writes them to output pipe, and terminates.
$ read -r first_line <&${head[0]}
[1]- Done             coproc head { head -n 10; }
$ read -r second_line <&${head[0]}
# address@hidden is already unset, and pipes closed, so...
-bash: ${head[0]}: ambiguous redirect


Fix:
Perhaps the simplest fix is just don't close the pipes or unset the
variable. Leave that up to the caller.

Another option might be to use poll() to check if the pipe is empty
prior to closing it:

poll_fd.events = (POLLHUP | POLLIN);
int poll_result = poll(&poll_fd, 1, 0);
// Then don't close the file descriptor until
// (!(poll_fd.revents & POLLIN) && (poll_fd.revents & POLLHUP)).

But this is still problematic: Suppose the shell script is running a
loop, processing lines of text from the coproc:

$ while read line <&${coproc[0]}; do cmd $line; done

Even if the pipe isn't closed until all the data has been read out of
it, the loop may (depending on timing) wind up terminating with an
"ambiguous redirect" error (or "unbound variable" if "nounset" is in
effect), when it should have ended happily with an EOF condition.

Users can work around this by duplicating the file descriptor:
$ exec {fd_that_wont_vanish_on_me}<&${coproc[0]}-
But it kind of negates the benefit of having coproc accept a name for
the fd array if you just wind up having to re-bind it anyway. And the
command could still fail if it's not run immediately after launching
the coproc.

Thus, I think coproc shouldn't close its file descriptors or erase its
environment variables.

---GEC





reply via email to

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