Browse Source

Merge branch 'rs/daemon-plug-child-leak'

"git daemon" uses "run_command()" without "finish_command()", so it
needs to release resources itself, which it forgot to do.

* rs/daemon-plug-child-leak:
  daemon: plug memory leak
  run-command: factor out child_process_clear()
maint
Junio C Hamano 9 years ago
parent
commit
c3c592ef95
  1. 7
      Documentation/technical/api-run-command.txt
  2. 1
      daemon.c
  3. 15
      run-command.c
  4. 1
      run-command.h

7
Documentation/technical/api-run-command.txt

@ -46,6 +46,13 @@ Functions
The argument dir corresponds the member .dir. The argument env The argument dir corresponds the member .dir. The argument env
corresponds to the member .env. corresponds to the member .env.


`child_process_clear`::

Release the memory associated with the struct child_process.
Most users of the run-command API don't need to call this
function explicitly because `start_command` invokes it on
failure and `finish_command` calls it automatically already.

The functions above do the following: The functions above do the following:


. If a system call failed, errno is set and -1 is returned. A diagnostic . If a system call failed, errno is set and -1 is returned. A diagnostic

1
daemon.c

@ -802,6 +802,7 @@ static void check_dead_children(void)
/* remove the child */ /* remove the child */
*cradle = blanket->next; *cradle = blanket->next;
live_children--; live_children--;
child_process_clear(&blanket->cld);
free(blanket); free(blanket);
} else } else
cradle = &blanket->next; cradle = &blanket->next;

15
run-command.c

@ -11,6 +11,12 @@ void child_process_init(struct child_process *child)
argv_array_init(&child->env_array); argv_array_init(&child->env_array);
} }


void child_process_clear(struct child_process *child)
{
argv_array_clear(&child->args);
argv_array_clear(&child->env_array);
}

struct child_to_clean { struct child_to_clean {
pid_t pid; pid_t pid;
struct child_to_clean *next; struct child_to_clean *next;
@ -327,8 +333,7 @@ int start_command(struct child_process *cmd)
fail_pipe: fail_pipe:
error("cannot create %s pipe for %s: %s", error("cannot create %s pipe for %s: %s",
str, cmd->argv[0], strerror(failed_errno)); str, cmd->argv[0], strerror(failed_errno));
argv_array_clear(&cmd->args); child_process_clear(cmd);
argv_array_clear(&cmd->env_array);
errno = failed_errno; errno = failed_errno;
return -1; return -1;
} }
@ -513,8 +518,7 @@ fail_pipe:
close_pair(fderr); close_pair(fderr);
else if (cmd->err) else if (cmd->err)
close(cmd->err); close(cmd->err);
argv_array_clear(&cmd->args); child_process_clear(cmd);
argv_array_clear(&cmd->env_array);
errno = failed_errno; errno = failed_errno;
return -1; return -1;
} }
@ -540,8 +544,7 @@ fail_pipe:
int finish_command(struct child_process *cmd) int finish_command(struct child_process *cmd)
{ {
int ret = wait_or_whine(cmd->pid, cmd->argv[0], 0); int ret = wait_or_whine(cmd->pid, cmd->argv[0], 0);
argv_array_clear(&cmd->args); child_process_clear(cmd);
argv_array_clear(&cmd->env_array);
return ret; return ret;
} }



1
run-command.h

@ -47,6 +47,7 @@ struct child_process {


#define CHILD_PROCESS_INIT { NULL, ARGV_ARRAY_INIT, ARGV_ARRAY_INIT } #define CHILD_PROCESS_INIT { NULL, ARGV_ARRAY_INIT, ARGV_ARRAY_INIT }
void child_process_init(struct child_process *); void child_process_init(struct child_process *);
void child_process_clear(struct child_process *);


int start_command(struct child_process *); int start_command(struct child_process *);
int finish_command(struct child_process *); int finish_command(struct child_process *);

Loading…
Cancel
Save