Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: process substitution and Ctrl-C



On Aug 19,  2:41pm, Vincent Lefevre wrote:
} 
} In the following example:
} 
}   { repeat 10 { date >&2; /bin/sleep 1 } } 2>>(cat -n; loop)
} 
} where "loop" is a program that consumes CPU time, is it normal that
} when one interrupts the command with Ctrl-C, the substituted process
} isn't killed? (I can see "loop" taking CPU time.)

The assumption is that process substitution consumes stdin and exits
after its stdin is closed.  Otherwise, why would you need to redirect
into it?

However, there may be a good reason for changing this.  If I try

    echo >>(cat; sleep 100)

then the shell is effectively frozen until "sleep 100" finishes, because
"echo" is already gone and the process substitution is not interruptible,
so nothing is paying attention to ^C or ^Z etc.  This appears to happen
with any builtin as the input to the process substitution, including a
brace construct like the one you used above; e.g. I tried:

    { tty } >>(cat; sleep 100)

and it hangs there for 100 seconds.  However, it doesn't happen with an
external command; e.g.

    tty >>(cat; sleep 100)

exits immediately, even before the sleep finishes, though the sleep is
left running.

} The zsh man page says that the command is run asynchronously, but
} this notion is never clearly defined.

For better or worse, the zsh man page has never been very good about
fully defining concepts that are "well known" from other shells.  It
was written from the standpoint of "you've already used (c)sh for a
while and know what all of this means, I'm just going to tell you what
is different about doing it in zsh."

So if you refer to (say) the bash manual:

   A shell allows execution of GNU commands, both synchronously and
   asynchronously. The shell waits for synchronous commands to complete
   before accepting more input; asynchronous commands continue to
   execute in parallel with the shell while it reads and executes
   additional commands.

   Command substitution, commands grouped with parentheses, and
   asynchronous commands are invoked in a subshell environment that is
   a duplicate of the shell environment, except that traps caught by
   the shell are reset to the values that the shell inherited from its
   parent at invocation.

   When job control is not in effect, asynchronous commands ignore
   `SIGINT' and `SIGQUIT' in addition to these inherited handlers.
   Commands run as a result of command substitution ignore the
   keyboard-generated job control signals `SIGTTIN', `SIGTTOU', and
   `SIGTSTP'.

What gets fuzzy, even in the bash manual, is the distinction between
an "asynchronous command" and a "background job":

   If a command is terminated by the control operator `&', the shell
   executes the command asynchronously in a subshell. This is known as
   executing the command in the BACKGROUND. The shell does not wait for
   the command to finish, and the return status is 0 (true). When job
   control is not active, the standard input for asynchronous commands,
   in the absence of any explicit redirections, is redirected from
   `/dev/null'.

   Background processes are those whose process group ID differs from
   the terminal's; such processes are immune to keyboard-generated
   signals. Only foreground processes are allowed to read from or write
   to the terminal. Background processes which attempt to read from
   (write to) the terminal are sent a `SIGTTIN' (`SIGTTOU') signal by
   the terminal driver, which, unless caught, suspends the process.

Zsh process substitution (and, I think, just about everything that zsh
runs "asynchronously") behave in almost every way like background jobs,
and therefore don't receive keyboard-generated signals.



Messages sorted by: Reverse Date, Date, Thread, Author