Bug 180178

Summary: shells/zsh: hangs upon '>(command)' redirections
Product: Ports & Packages Reporter: danielsh
Component: Individual Port(s)Assignee: Baptiste Daroussin <bapt>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: Latest   
Hardware: Any   
OS: Any   

Description danielsh 2013-07-01 20:30:00 UTC
zsh hangs when commands involving '>(command)' are involved:

[[[
% ssh loki.apache.org 'zsh -fc "echo >(wc -l)"' 
/tmp/zshJHGd5f

]]]

It responds to ^C and ^Z but not to ^D or ^\.

Using ':' or 'true' inside the parentheses yields the same behaviour.

Fix: 

The problem does not appear on either OpenBSD or Linux:

% ssh openbsdbox 'zsh -fc "echo >(true)"' 
/dev/fd/12
% ssh linuxbox 'zsh -fc "echo >(true)"'             
/proc/self/fd/12
How-To-Repeat: zsh -fc "echo >(:)"

OR

zsh -fc ">(:)"
Comment 1 Edwin Groothuis freebsd_committer freebsd_triage 2013-07-01 20:30:09 UTC
Responsible Changed
From-To: freebsd-ports-bugs->bapt

Over to maintainer (via the GNATS Auto Assign Tool)
Comment 2 Jilles Tjoelker freebsd_committer freebsd_triage 2014-04-05 13:56:55 UTC
In FreeBSD PR ports/180178, you wrote:
> zsh hangs when commands involving '>(command)' are involved:

> [[[
> % ssh loki.apache.org 'zsh -fc "echo >(wc -l)"'
> /tmp/zshJHGd5f
> ]]]

> It responds to ^C and ^Z but not to ^D or ^\.

> Using ':' or 'true' inside the parentheses yields the same behaviour.

A construct like >(CMD) is called process substitution and expands to a
pathname that, when opened, writes to the standard input of CMD. In zsh
(but not bash), the shell also waits for CMD to terminate when the outer
command is done.

The similar <(CMD) expands to a pathname that reads from the standard
output of CMD; the shell does not wait for CMD to terminate.

Depending on whether the full /dev/fd was available when zsh was
compiled (look for zsh_cv_sys_path_dev_fd in configure.ac), zsh uses
either /dev/fd or a fifo to generate the pathname. There is a special
case for redirecting to or from a process substitution which uses an
unnamed pipe.

If zsh uses a fifo, the child process will block until the generated
pathname is opened. If the pathname is never opened, such as when you
echo it, the child process blocks indefinitely. It might be possible to
fix this in zsh by opening the fifo with O_NONBLOCK before deleting it.

If zsh uses /dev/fd, such as when the port is compiled using poudriere,
process substitution does not work unless the full /dev/fd (fdescfs) is
mounted (by default, only /dev/fd/0, /dev/fd/1 and /dev/fd/2 are
available which is not good enough).

-- 
Jilles Tjoelker