Skip to content

Commit

Permalink
run-command: do not pass child process data into callbacks
Browse files Browse the repository at this point in the history
The expected way to pass data into the callback is to pass them via
the customizable callback pointer. The error reporting in
default_{start_failure, task_finished} is not user friendly enough, that
we want to encourage using the child data for such purposes.

Furthermore the struct child data is cleaned by the run-command API,
before we access them in the callbacks, leading to use-after-free
situations.

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
stefanbeller authored and gitster committed Mar 1, 2016
1 parent 62104ba commit 2a73b3d
Show file tree
Hide file tree
Showing 4 changed files with 9 additions and 32 deletions.
24 changes: 3 additions & 21 deletions run-command.c
Expand Up @@ -902,35 +902,18 @@ struct parallel_processes {
struct strbuf buffered_output; /* of finished children */
};

static int default_start_failure(struct child_process *cp,
struct strbuf *err,
static int default_start_failure(struct strbuf *err,
void *pp_cb,
void *pp_task_cb)
{
int i;

strbuf_addstr(err, "Starting a child failed:");
for (i = 0; cp->argv[i]; i++)
strbuf_addf(err, " %s", cp->argv[i]);

return 0;
}

static int default_task_finished(int result,
struct child_process *cp,
struct strbuf *err,
void *pp_cb,
void *pp_task_cb)
{
int i;

if (!result)
return 0;

strbuf_addf(err, "A child failed with return code %d:", result);
for (i = 0; cp->argv[i]; i++)
strbuf_addf(err, " %s", cp->argv[i]);

return 0;
}

Expand Down Expand Up @@ -1048,8 +1031,7 @@ static int pp_start_one(struct parallel_processes *pp)
pp->children[i].process.no_stdin = 1;

if (start_command(&pp->children[i].process)) {
code = pp->start_failure(&pp->children[i].process,
&pp->children[i].err,
code = pp->start_failure(&pp->children[i].err,
pp->data,
&pp->children[i].data);
strbuf_addbuf(&pp->buffered_output, &pp->children[i].err);
Expand Down Expand Up @@ -1117,7 +1099,7 @@ static int pp_collect_finished(struct parallel_processes *pp)

code = finish_command(&pp->children[i].process);

code = pp->task_finished(code, &pp->children[i].process,
code = pp->task_finished(code,
&pp->children[i].err, pp->data,
&pp->children[i].data);

Expand Down
9 changes: 3 additions & 6 deletions run-command.h
Expand Up @@ -158,8 +158,7 @@ typedef int (*get_next_task_fn)(struct child_process *cp,
* To send a signal to other child processes for abortion, return
* the negative signal number.
*/
typedef int (*start_failure_fn)(struct child_process *cp,
struct strbuf *err,
typedef int (*start_failure_fn)(struct strbuf *err,
void *pp_cb,
void *pp_task_cb);

Expand All @@ -178,7 +177,6 @@ typedef int (*start_failure_fn)(struct child_process *cp,
* the negative signal number.
*/
typedef int (*task_finished_fn)(int result,
struct child_process *cp,
struct strbuf *err,
void *pp_cb,
void *pp_task_cb);
Expand All @@ -192,9 +190,8 @@ typedef int (*task_finished_fn)(int result,
* (both stdout and stderr) is routed to stderr in a manner that output
* from different tasks does not interleave.
*
* If start_failure_fn or task_finished_fn are NULL, default handlers
* will be used. The default handlers will print an error message on
* error without issuing an emergency stop.
* start_failure_fn and task_finished_fn can be NULL to omit any
* special handling.
*/
int run_processes_parallel(int n,
get_next_task_fn,
Expand Down
7 changes: 3 additions & 4 deletions submodule.c
Expand Up @@ -705,8 +705,7 @@ static int get_next_submodule(struct child_process *cp,
return 0;
}

static int fetch_start_failure(struct child_process *cp,
struct strbuf *err,
static int fetch_start_failure(struct strbuf *err,
void *cb, void *task_cb)
{
struct submodule_parallel_fetch *spf = cb;
Expand All @@ -716,8 +715,8 @@ static int fetch_start_failure(struct child_process *cp,
return 0;
}

static int fetch_finish(int retvalue, struct child_process *cp,
struct strbuf *err, void *cb, void *task_cb)
static int fetch_finish(int retvalue, struct strbuf *err,
void *cb, void *task_cb)
{
struct submodule_parallel_fetch *spf = cb;

Expand Down
1 change: 0 additions & 1 deletion test-run-command.c
Expand Up @@ -41,7 +41,6 @@ static int no_job(struct child_process *cp,
}

static int task_finished(int result,
struct child_process *cp,
struct strbuf *err,
void *pp_cb,
void *pp_task_cb)
Expand Down

0 comments on commit 2a73b3d

Please sign in to comment.