From: Bart Schaefer <schaefer@brasslantern.com>
To: "Zsh Hackers' List" <zsh-workers@zsh.org>
Subject: Multio deadlock (Re: multios doesn't work with 2>&1)
Date: Sun, 27 Oct 2013 12:39:17 -0700 [thread overview]
Message-ID: <131027123917.ZM27930@torch.brasslantern.com> (raw)
In-Reply-To: <131027112724.ZM16426@torch.brasslantern.com>
On Oct 27, 11:27am, Bart Schaefer wrote:
}
} } echo foo >/dev/null 2>&1 | sed 's/foo/bar/'
} }
} } gives a different bad effect, namely you get the output you want but the
} } shell hangs
}
} The parent shell is in zwaitjob(), as is the shell that spawned sed.
That should actually say "as is the shell that was forked for echo".
The parent shell is waiting for "sed".
Here's the spot where the "echo" shell is stopped:
/*
* So what's going on here then? Well, I'm glad you asked.
*
* If we create multios for use in a subshell we do
* this after forking, in this function above. That
* means that the current (sub)process is responsible
* for clearing them up. However, the processes won't
* go away until we have closed the fd's talking to them.
* Since we're about to exit the shell there's nothing
* to stop us closing all fd's (including the ones 0 to 9
* that we usually leave alone).
*
* Then we wait for any processes. When we forked,
* we cleared the jobtable and started a new job just for
* any oddments like this, so if there aren't any we won't
* need to wait. The result of not waiting is that
* the multios haven't flushed the fd's properly, leading
* to obscure missing data.
*
* It would probably be cleaner to ensure that the
* parent shell handled multios, but that requires
* some architectural changes which are likely to be
* hairy.
*/
for (i = 0; i < 10; i++)
if (fdtable[i] != FDT_UNUSED)
close(i);
closem(FDT_UNUSED);
if (thisjob != -1)
waitjobs();
_exit(lastval);
Obviously we've not succeeded in closing all the necessary descriptors.
Here's what's still open (PID 16361 == parent, 16383 == echo, 16384 == /*
* So what's going on here then? Well, I'm glad you asked.
*
* If we create multios for use in a subshell we do
* this after forking, in this function above. That
* means that the current (sub)process is responsible
* for clearing them up. However, the processes won't
* go away until we have closed the fd's talking to them.
* Since we're about to exit the shell there's nothing
* to stop us closing all fd's (including the ones 0 to 9
* that we usually leave alone).
*
* Then we wait for any processes. When we forked,
* we cleared the jobtable and started a new job just for
* any oddments like this, so if there aren't any we won't
* need to wait. The result of not waiting is that
* the multios haven't flushed the fd's properly, leading
* to obscure missing data.
*
* It would probably be cleaner to ensure that the
* parent shell handled multios, but that requires
* some architectural changes which are likely to be
* hairy.
*/
for (i = 0; i < 10; i++)
if (fdtable[i] != FDT_UNUSED)
close(i);
closem(FDT_UNUSED);
if (thisjob != -1)
waitjobs();
_exit(lastval);
Obviously we've not succeeded in closing all the necessary descriptors.
Here's what's still open:
zsh 16361 16361 schaefer 0u CHR 136,3 5 /dev/pts/3
zsh 16361 16361 schaefer 1u CHR 136,3 5 /dev/pts/3
zsh 16361 16361 schaefer 2u CHR 136,3 5 /dev/pts/3
zsh 16361 16361 schaefer 10u CHR 136,3 5 /dev/pts/3
zsh 16383 16383 schaefer 2w FIFO 0,7 1227018 pipe
zsh 16384 16383 schaefer 12w FIFO 0,7 1227016 pipe
zsh 16384 16383 schaefer 13w CHR 1,3 2056 /dev/null
zsh 16384 16383 schaefer 14r FIFO 0,7 1227018 pipe
sed 16385 16383 schaefer 0r FIFO 0,7 1227016 pipe
sed 16385 16383 schaefer 1u CHR 136,3 5 /dev/pts/3
sed 16385 16383 schaefer 2u CHR 136,3 5 /dev/pts/3
16361 is the parent, it's clean. 16383 is echo and 16384 is the multio.
The multio is blocked reading fd 14 (1227018 pipe), which it's parent
still has open as stderr because fdtable[2] == FDT_UNUSED.
Does the following look right? It does fix the deadlock, but we might
call close() on an already closed fd, which it appears this is trying
to avoid (maybe so as not to change errno?).
diff --git a/Src/exec.c b/Src/exec.c
index 99c7eaa..7ac1ad5 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -3372,7 +3372,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
* hairy.
*/
for (i = 0; i < 10; i++)
- if (fdtable[i] != FDT_UNUSED)
+ if (i < 3 || fdtable[i] != FDT_UNUSED)
close(i);
closem(FDT_UNUSED);
if (thisjob != -1)
next prev parent reply other threads:[~2013-10-27 19:39 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20131027145917.GA5509@localhost.localdomain>
[not found] ` <131027100137.ZM4100@torch.brasslantern.com>
2013-10-27 17:46 ` multios doesn't work with 2>&1 Peter Stephenson
2013-10-27 18:27 ` Bart Schaefer
2013-10-27 19:39 ` Bart Schaefer [this message]
2013-10-27 20:24 ` Multio deadlock (Re: multios doesn't work with 2>&1) Bart Schaefer
2013-10-27 20:33 ` Peter Stephenson
2013-10-27 21:16 ` Peter Stephenson
2013-10-27 22:31 ` Bart Schaefer
2013-10-27 22:18 ` Bart Schaefer
2013-10-27 18:11 ` multios doesn't work with 2>&1 Bart Schaefer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=131027123917.ZM27930@torch.brasslantern.com \
--to=schaefer@brasslantern.com \
--cc=zsh-workers@zsh.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/zsh/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).