Re: [PATCH 6/8] run-command: add an asynchronous parallel child processor
- From
Johannes Sixt <j6t@kdbg.org>
- Date
- Dec 14, 2015, 20:39 UTC
- Message-ID
- <566F28EA.3080802@kdbg.org>
- In-Reply-To
- <1450121838-7069-7-git-send-email-sbeller@google.com>
Am 14.12.2015 um 20:37 schrieb Stefan Beller:
Show 58 quoted lines
> This allows to run external commands in parallel with ordered output > on stderr. > > If we run external commands in parallel we cannot pipe the output directly > to the our stdout/err as it would mix up. So each process's output will > flow through a pipe, which we buffer. One subprocess can be directly > piped to out stdout/err for a low latency feedback to the user. > > Example: > Let's assume we have 5 submodules A,B,C,D,E and each fetch takes a > different amount of time as the different submodules vary in size, then > the output of fetches in sequential order might look like this: > > time --> > output: |---A---| |-B-| |-------C-------| |-D-| |-E-| > > When we schedule these submodules into maximal two parallel processes, > a schedule and sample output over time may look like this: > > process 1: |---A---| |-D-| |-E-| > > process 2: |-B-| |-------C-------| > > output: |---A---|B|---C-------|DE > > So A will be perceived as it would run normally in the single child > version. As B has finished by the time A is done, we can dump its whole > progress buffer on stderr, such that it looks like it finished in no > time. Once that is done, C is determined to be the visible child and > its progress will be reported in real time. > > So this way of output is really good for human consumption, as it only > changes the timing, not the actual output. > > For machine consumption the output needs to be prepared in the tasks, > by either having a prefix per line or per block to indicate whose tasks > output is displayed, because the output order may not follow the > original sequential ordering: > > |----A----| |--B--| |-C-| > > will be scheduled to be all parallel: > > process 1: |----A----| > process 2: |--B--| > process 3: |-C-| > output: |----A----|CB > > This happens because C finished before B did, so it will be queued for > output before B. > > The detection when a child has finished executing is done the same way as > two fold. First we check regularly if the stderr pipe still exists in an > interleaved manner with other actions such as checking other children > for their liveliness or starting new children. Once a child closed their > stderr stream, we assume it is stopping very soon, such that we can use > the `finish_command` code borrowed from the single external process > execution interface.
I can't quite parse the first sentence in this paragraph. Perhaps something like this:
To detect when a child has finished executing, we check interleaved with other actions (such as checking the liveliness of children or starting new processes) whether the stderr pipe still exists. Once a child closed its stderr stream, we assume it is terminating very soon, and use finish_command() from the single external process execution interface to collect the exit status.
Show 6 quoted lines
> > By maintaining the strong assumption of stderr being open until the > very end of a child process, we can avoid other hassle such as an > implementation using `waitpid(-1)`, which is not implemented in Windows. > > Signed-off-by: Stefan Beller <sbeller@google.com>