Junio C Hamano <gitster@xxxxxxxxx> writes: > Subject: [PATCH] fsck: clear child_process after failed run_command() > > There are two loops that calls run_command() using the same > child_process struct near the end of cmd_fsck(). 4d0984be (fsck: do > not reuse child_process structs, 2018-11-12) tightened these code > paths to reinitialize the structure in order to safely reuse it. > > The run-command API makes no promises about what is left in a struct > child_process after a command finishes, and it's not safe to simply > reuse it again for a similar command. > > Upon failure, run_command() can return without releasing the > resource held by the child_process structure, which is done by > calling finish_command() which in turn calls child_process_clear(). Sorry, but I have to take this back. The error return code paths in the start_command() function does seem to call clear_child_process(), which means that there is no need to call clear_child_process() ourselves after a failed run_command() call. The need for reinitializing that established by 4d0984be (fsck: do not reuse child_process structs, 2018-11-12) still stand, so ... the first run ... run_command(&cp); /* no need for separate child_process_clear(&cp) */ child_process_init(&cp); /* prepare for reuse */ ... setup for the second run ... strvec_pushv(&cp.args, diff_index_args); cp.git_cmd = 1; ... full set-up without relying on anything done earlier ... would still be needed. Or alternatively, we could do this to ensure that the child_process structure is always reusable. run-command.c | 1 + run-command.h | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git c/run-command.c w/run-command.c index 6ac1d14516..aba250fbe1 100644 --- c/run-command.c +++ w/run-command.c @@ -26,6 +26,7 @@ void child_process_clear(struct child_process *child) { strvec_clear(&child->args); strvec_clear(&child->env); + child_process_init(child); } struct child_to_clean { diff --git c/run-command.h w/run-command.h index 55f6631a2a..6e203c22f6 100644 --- c/run-command.h +++ w/run-command.h @@ -204,7 +204,8 @@ int start_command(struct child_process *); /** * Wait for the completion of a sub-process that was started with - * start_command(). + * start_command(). The child_process structure is cleared and + * reinitialized. */ int finish_command(struct child_process *); @@ -214,6 +215,9 @@ int finish_command_in_signal(struct child_process *); * A convenience function that encapsulates a sequence of * start_command() followed by finish_command(). Takes a pointer * to a `struct child_process` that specifies the details. + * The child_process structure is cleared and reinitialized, + * even when the command fails to start or an error is detected + * in finish_command(). */ int run_command(struct child_process *);