Subject: Re: [PATCH v2 2/5] run-command: allow stdin for run_processes_parallel

From: Junio C Hamano <[email-masked]>
Date: Wed, 08 Feb 2023 13:09:26 -0800

Ævar Arnfjörð Bjarmason  <[email-masked]> writes:

> From: Emily Shaffer <[email-masked]>
>
> While it makes sense not to inherit stdin from the parent process to
> avoid deadlocking, it's not necessary to completely ban stdin to
> children.

I do not think deadlock avoidance is an issue.  Unpredictable
feeding of pieces of input into multiple children is.  One possible
semantics is to grab the input and dup/tee into all the children, so 
that each child gets its own copy to process.  A hook like "pre-receive",
when it has more than one scripts listening to the event, may want
such a semantics.  Another possible semantics is to give priority
among the children running simultaneously and feed only one child,
while starving others.

> An informed user should be able to configure stdin safely. By
> setting `some_child.process.no_stdin=1` before calling `get_next_task()`
> we provide a reasonable default behavior but enable users to set up
> stdin streaming for themselves during the callback.

I _think_ this alludes to the latter, e.g. "only one child is
allowed, and the one that controls what children are spawned sets
no_stdin for everybody but the chosen one".  We may want to be a bit
more explicit in the proposed log message and definitely in the
documentation.

The implementation is "nice".

> +	/*
> +	 * By default, do not inherit stdin from the parent process - otherwise,
> +	 * all children would share stdin! Users may overwrite this to provide
> +	 * something to the child's stdin by having their 'get_next_task'
> +	 * callback assign 0 to .no_stdin and an appropriate integer to .in.
> +	 */
> +	pp->children[i].process.no_stdin = 1;
> +
>  	code = opts->get_next_task(&pp->children[i].process,
>  				   opts->ungroup ? NULL : &pp->children[i].err,
>  				   opts->data,
> @@ -1601,7 +1609,6 @@ static int pp_start_one(struct parallel_processes *pp,
>  		pp->children[i].process.err = -1;
>  		pp->children[i].process.stdout_to_stderr = 1;
>  	}
> -	pp->children[i].process.no_stdin = 1;
>  
>  	if (start_command(&pp->children[i].process)) {
>  		if (opts->start_failure)