Merge branch 'rs/daemon-plug-child-leak'
authorJunio C Hamano <gitster@pobox.com>
Tue, 3 Nov 2015 23:13:11 +0000 (15:13 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 3 Nov 2015 23:13:12 +0000 (15:13 -0800)
"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()

Documentation/technical/api-run-command.txt
daemon.c
run-command.c
run-command.h
index a9fdb45b93e514962716401cb22d9d079b107e40..8bf3e37f5375584e5c9f4543523a40377e08686f 100644 (file)
@@ -46,6 +46,13 @@ Functions
        The argument dir corresponds the member .dir. The argument 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:
 
 . If a system call failed, errno is set and -1 is returned. A diagnostic
index 56679a15fee533a29168b92ecc0f18f68f919085..be70cd4da09ccab8850be41e19b0fc4b9a10f502 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -802,6 +802,7 @@ static void check_dead_children(void)
                        /* remove the child */
                        *cradle = blanket->next;
                        live_children--;
+                       child_process_clear(&blanket->cld);
                        free(blanket);
                } else
                        cradle = &blanket->next;
index e17e456cdaef63d3fa587b8e216bf1fe5c372317..13fa452e8c3d5a5e20e24a969d53ce7ade4019bf 100644 (file)
@@ -11,6 +11,12 @@ void child_process_init(struct child_process *child)
        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 {
        pid_t pid;
        struct child_to_clean *next;
@@ -327,8 +333,7 @@ int start_command(struct child_process *cmd)
 fail_pipe:
                        error("cannot create %s pipe for %s: %s",
                                str, cmd->argv[0], strerror(failed_errno));
-                       argv_array_clear(&cmd->args);
-                       argv_array_clear(&cmd->env_array);
+                       child_process_clear(cmd);
                        errno = failed_errno;
                        return -1;
                }
@@ -513,8 +518,7 @@ int start_command(struct child_process *cmd)
                        close_pair(fderr);
                else if (cmd->err)
                        close(cmd->err);
-               argv_array_clear(&cmd->args);
-               argv_array_clear(&cmd->env_array);
+               child_process_clear(cmd);
                errno = failed_errno;
                return -1;
        }
@@ -540,8 +544,7 @@ int start_command(struct child_process *cmd)
 int finish_command(struct child_process *cmd)
 {
        int ret = wait_or_whine(cmd->pid, cmd->argv[0], 0);
-       argv_array_clear(&cmd->args);
-       argv_array_clear(&cmd->env_array);
+       child_process_clear(cmd);
        return ret;
 }
 
index 5428b048e2c49dec3e322ac2a46ffddd012e4c8d..12bb26c2a6155750203babfec47b08e8bde0ad27 100644 (file)
@@ -47,6 +47,7 @@ struct child_process {
 
 #define CHILD_PROCESS_INIT { NULL, ARGV_ARRAY_INIT, ARGV_ARRAY_INIT }
 void child_process_init(struct child_process *);
+void child_process_clear(struct child_process *);
 
 int start_command(struct child_process *);
 int finish_command(struct child_process *);