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

Forking earlier for background code

I've renamed this part of the previous pipeline + process group thread.

This patch:

> This is a first go that doesn't appear to be completely broken.  Lots
> of rearranging and reindenting, very little novel code.  I'm not sure
> how much git users feel like being guinea pigs.

to fork earlier when a process is being put into the background looks
fairly benign to me, so I'll commit it (with a few more comments) in
order to see what oddities we can track down.

This was the easy case because the test for (how & Z_ASYNC) wasn't
combined with anything else. so factored out trivially.

Deep breath.

It may well be possible to expand the logic to track down other cases
where we know we can know we're going to need to fork, so can do so early
to get fewer side effects (and slightly optimise the main shell).
However, we're going to have to disentangle the code shown below.  At
the moment this relies on us being able to expand the command line to
decide if the command is a builtin or shell.  However, with enough
banging of heads against granite outcrops it might be possible to
rationalise what's going on with "do_exec", "output" and "last1" enough
so this isn't always necessary.

"last1" --- at the end of the exec list and also the pipeline:  it's
effectively an "and" of choices made in execlist() and execpline2().
Note special case below.

"do_exec" --- last1 and doing an exec, so no need to fork.

"output" --- output of pipeline, so zero if not a pipeline (we never
pipe output to fd 0).

The "if (!forked)" test is the result of the new early fork.

One complication is in execpline2() where it says

	/* if we are doing "foo | bar" where foo is a current *
	 * shell command, do foo in a subshell and do the     *
	 * rest of the pipeline in the current shell.         */

I think this may just be an early attempt to get the effects Stephane
wants?  In any case, last1 is passed down to execcmd as 1 here so we
don't fork again (except the logic is complicated enough it's not
obvious to me that's necessarily true).

So I think if "last1" is zero and "output" is non-zero we might be able to
fork early, perhaps?  And possibly if we do that the special code in
execpline2() becomes redundant, maybe?  So then we only need to be
sensitive to "output", perhaps maybe?

(I don't suppose anybody actually understands this?)

     * Do we need to fork?  We need to fork if:                               *
     * 1) The command is supposed to run in the background.  This             *
     *    case is now handled above (forked = 1 here). (or)                   *
     * 2) There is no `exec' flag, and either:                                *
     *    a) This is a builtin or shell function with output piped somewhere. *
     *    b) This is an external command and we can't do a `fake exec'.       *
     *                                                                        *
     * A `fake exec' is possible if we have all the following conditions:     *
     * 1) last1 flag is 1.  This indicates that the current shell will not    *
     *    be needed after the current command.  This is typically the case    *
     *    when the command is the last stage in a subshell, or is the         *
     *    last command after the option `-c'.                                 *
     * 2) We don't have any traps set.                                        *
     * 3) We don't have any files to delete.                                  *
     *                                                                        *
     * The condition above for a `fake exec' will also work for a current     *
     * shell command such as a builtin, but doesn't really buy us anything    *
     * (doesn't save us a process), since it is already running in the        *
     * current shell.                                                         *

    if (!forked) {
	if (!do_exec &&
	    (((is_builtin || is_shfunc) && output) ||
	     (!is_cursh && (last1 != 1 || nsigtrapped || havefiles() ||
			    fdtable_flocks)))) {


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