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

Re: command substitution: zsh waits until command exits

On 2007-12-02 10:27:15 -0800, Bart Schaefer wrote:
> On Dec 2,  4:22pm, Vincent Lefevre wrote:
> } The substituted command doesn't need to be finished to be able to
> } build the argument list: its standard output just needs to be closed
> } (which is what I did in my example).
> This discussion is getting sort of cyclical.  It doesn't work that way.
> It doesn't work that way in any other shell, either, never has, and
> although I don't have it handy I'm pretty sure the POSIX spec would
> prohibit it from working that way.

POSIX just says:

  The shell shall expand the command substitution by executing command
  in a subshell environment (see Shell Execution Environment) and
  replacing the command substitution (the text of command plus the
  enclosing "$()" or backquotes) with the standard output of the
  command, removing sequences of one or more <newline>s at the end of
  the substitution. Embedded <newline>s before the end of the output
  shall not be removed; however, they may be treated as field
  delimiters and eliminated during field splitting, depending on the
  value of IFS and quoting that is in effect.

I don't think this is prohibited. Even pipeline completion is
implementation defined:

  If the pipeline is not in the background (see Asynchronous Lists),
  the shell shall wait for the last command specified in the pipeline
  to complete, and may also wait for all commands to complete.

> You'll also note that even though "cat" finishes in
>    { echo ab; exec 1>&-; sleep 5 } | cat
> the parent shell does not return to a prompt until the sleep finishes.

Yes, and POSIX shells can choose to return immediately (see above).

> That's the real analogy to what's happening with $(...).

In which case, you should agree that a POSIX shell may do the
substitution while the command has not terminated (if the standard
output has been closed, of course).

Now, in both cases, zsh should document what it's doing.

> This seems to do what you want by restoring the interactive handlers:
> echo $(coproc xterm -e 'zsh -fic "tty >&3 ; exec sleep 999999"' 3>&1 ;
>        read -E <&p)
> Or this, which doesn't rely on coproc:
> echo $({ xterm -e 'zsh -fic "tty >&3 ; exec sleep 999999"' 3>&1 & } |
>        read -E)

Both are working. Is there one of them that is better?

> The zsh -fic is still needed there so I think it may be $(...) that's
> ignoring interrupts, which possibly it should not do.

FYI, under Mac OS X, with both

echo $({ xterm -e 'sh -c "tty >&3 ; exec sleep 999999"' 3>&1 & } | read -E)


echo $({ xterm -e 'sh -ic "tty >&3 ; exec sleep 999999"' 3>&1 & } | read -E)

Ctrl-C is ignored (but Ctrl-\ still works).

> } > Incidentally I use this little function all the time:
> } > 
> } > gdbterm () {
> } >     xterm -title GDBterm -e sh -c 'exec xterm -e gdb --tty=$(tty) '"$*"
> } > }
> } 
> } but that's specific to gdb. And why starting two xterms?
> GDB runs in one, and the command run by GDB uses the other for I/O, and
> both of them close together when I exit GDB because the I/O xterm is the
> parent waiting for completion of the GDB xterm.

Thanks, that's interesting to know. It could be useful for me too...

Vincent Lefèvre <vincent@xxxxxxxxxx> - Web: <http://www.vinc17.org/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.org/blog/>
Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon)

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