git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v9 04/14] run-command: add wait_on_exit

From
larsxschneider@gmail.com <larsxschneider@gmail.com>
Date
Oct 4, 2016, 12:59 UTC
Message-ID
<20161004125947.67104-5-larsxschneider@gmail.com>
In-Reply-To
<20161004125947.67104-1-larsxschneider@gmail.com>
From: Lars Schneider <larsxschneider@gmail.com>

The flag 'clean_on_exit' kills child processes spawned by Git on exit. A hard kill like this might not be desired in all cases.

Add 'wait_on_exit' which closes the child's stdin on Git exit and waits until the child process has terminated.

The flag is used in a subsequent patch.
Signed-off-by: Lars Schneider <larsxschneider@gmail.com>
---
 run-command.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++--------
 run-command.h |  3 +++
 2 files changed, 50 insertions(+), 8 deletions(-)
diff --git a/run-command.c b/run-command.c
index 3269362..96c54fe 100644
--- a/run-command.c
+++ b/run-command.c
@@ -21,6 +21,9 @@ void child_process_clear(struct child_process *child)

 struct child_to_clean {
 	pid_t pid;
+	char *name;
+	int stdin;
+	int wait;
 	struct child_to_clean *next;
 };
 static struct child_to_clean *children_to_clean;
@@ -28,12 +31,33 @@ static int installed_child_cleanup_handler;

 static void cleanup_children(int sig, int in_signal)
 {
+	int status;
+	struct child_to_clean *p = children_to_clean;
+
+	/* Close the the child's stdin as indicator that Git will exit soon */
+	while (p) {
+		if (p->wait)
+			if (p->stdin > 0)
+				close(p->stdin);
+		p = p->next;
+	}
+
 	while (children_to_clean) {
-		struct child_to_clean *p = children_to_clean;
+		p = children_to_clean;
 		children_to_clean = p->next;
+
+		if (p->wait) {
+			fprintf(stderr, _("Waiting for '%s' to finish..."), p->name);
+			while ((waitpid(p->pid, &status, 0)) < 0 && errno == EINTR)
+				;	/* nothing */
+			fprintf(stderr, _("done!\n"));
+		}
+
 		kill(p->pid, sig);
-		if (!in_signal)
+		if (!in_signal) {
+			free(p->name);
 			free(p);
+		}
 	}
 }

@@ -49,10 +73,16 @@ static void cleanup_children_on_exit(void)
 	cleanup_children(SIGTERM, 0);
 }

-static void mark_child_for_cleanup(pid_t pid)
+static void mark_child_for_cleanup(pid_t pid, const char *name, int stdin, int wait)
 {
 	struct child_to_clean *p = xmalloc(sizeof(*p));
 	p->pid = pid;
+	p->wait = wait;
+	p->stdin = stdin;
+	if (name)
+		p->name = xstrdup(name);
+	else
+		p->name = "process";
 	p->next = children_to_clean;
 	children_to_clean = p;

@@ -63,6 +93,13 @@ static void mark_child_for_cleanup(pid_t pid)
 	}
 }

+#ifdef NO_PTHREADS
+static void mark_child_for_cleanup_no_wait(pid_t pid, const char *name, int timeout, int stdin)
+{
+	mark_child_for_cleanup(pid, NULL, 0, 0);
+}
+#endif
+
 static void clear_child_for_cleanup(pid_t pid)
 {
 	struct child_to_clean **pp;
@@ -421,8 +458,9 @@ int start_command(struct child_process *cmd)
 	}
 	if (cmd->pid < 0)
 		error_errno("cannot fork() for %s", cmd->argv[0]);
-	else if (cmd->clean_on_exit)
-		mark_child_for_cleanup(cmd->pid);
+	else if (cmd->clean_on_exit || cmd->wait_on_exit)
+		mark_child_for_cleanup(
+			cmd->pid, cmd->argv[0], cmd->in, cmd->wait_on_exit);

 	/*
 	 * Wait for child's execvp. If the execvp succeeds (or if fork()
@@ -482,8 +520,9 @@ int start_command(struct child_process *cmd)
 	failed_errno = errno;
 	if (cmd->pid < 0 && (!cmd->silent_exec_failure || errno != ENOENT))
 		error_errno("cannot spawn %s", cmd->argv[0]);
-	if (cmd->clean_on_exit && cmd->pid >= 0)
-		mark_child_for_cleanup(cmd->pid);
+	if ((cmd->clean_on_exit || cmd->wait_on_exit) && cmd->pid >= 0)
+		mark_child_for_cleanup(
+			cmd->pid, cmd->argv[0], cmd->in, cmd->clean_on_exit_timeout);

 	argv_array_clear(&nargv);
 	cmd->argv = sargv;
@@ -765,7 +804,7 @@ int start_async(struct async *async)
 		exit(!!async->proc(proc_in, proc_out, async->data));
 	}

-	mark_child_for_cleanup(async->pid);
+	mark_child_for_cleanup_no_wait(async->pid);

 	if (need_in)
 		close(fdin[0]);
diff --git a/run-command.h b/run-command.h
index cf29a31..f7b9907 100644
--- a/run-command.h
+++ b/run-command.h
@@ -42,7 +42,10 @@ struct child_process {
 	unsigned silent_exec_failure:1;
 	unsigned stdout_to_stderr:1;
 	unsigned use_shell:1;
+	 /* kill the child on Git exit */
 	unsigned clean_on_exit:1;
+	/* close the child's stdin on Git exit and wait until it terminates */
+	unsigned wait_on_exit:1;
 };

 #define CHILD_PROCESS_INIT { NULL, ARGV_ARRAY_INIT, ARGV_ARRAY_INIT }
--
2.10.0
Previous: larsxschneider@gmail.comNext: Junio C Hamano
Message 19 of 28 in “Git filter protocol”
  1. 00/14 Git filter protocollarsxschneider@gmail.com, Oct 4, 2016
  2. 02/14 convert: modernize testslarsxschneider@gmail.com, Oct 4, 2016
  3. 06/14 pkt-line: extract set_packet_header()larsxschneider@gmail.com, Oct 4, 2016
  4. 07/14 pkt-line: add packet_write_fmt_gently()larsxschneider@gmail.com, Oct 4, 2016
  5. 09/14 pkt-line: add packet_write_gently()larsxschneider@gmail.com, Oct 4, 2016
  6. Junio C HamanoOct 4, 2016
  7. Lars SchneiderOct 5, 2016
  8. Junio C HamanoOct 6, 2016
  9. 11/14 convert: make apply_filter() adhere to standard Git error handlinglarsxschneider@gmail.com, Oct 4, 2016
  10. 10/14 pkt-line: add functions to read/write flush terminated packet streamslarsxschneider@gmail.com, Oct 4, 2016
  11. Junio C HamanoOct 4, 2016
  12. Junio C HamanoOct 4, 2016
  13. Lars SchneiderOct 5, 2016
  14. 12/14 convert: prepare filter.<driver>.process optionlarsxschneider@gmail.com, Oct 4, 2016
  15. 13/14 convert: add filter.<driver>.process optionlarsxschneider@gmail.com, Oct 4, 2016
  16. 01/14 convert: quote filter names in error messageslarsxschneider@gmail.com, Oct 4, 2016
  17. 08/14 pkt-line: add packet_flush_gently()larsxschneider@gmail.com, Oct 4, 2016
  18. 14/14 contrib/long-running-filter: add long running filter examplelarsxschneider@gmail.com, Oct 4, 2016
  19. 04/14 run-command: add wait_on_exitlarsxschneider@gmail.com, Oct 4, 2016
  20. Junio C HamanoOct 4, 2016
  21. Lars SchneiderOct 5, 2016
  22. Junio C HamanoOct 5, 2016
  23. Johannes SchindelinOct 6, 2016
  24. Lars SchneiderOct 6, 2016
  25. Junio C HamanoOct 6, 2016
  26. 03/14 run-command: move check_pipe() from write_or_die to run_commandlarsxschneider@gmail.com, Oct 4, 2016
  27. 05/14 pkt-line: rename packet_write() to packet_write_fmt()larsxschneider@gmail.com, Oct 4, 2016
  28. Jakub NarębskiOct 5, 2016

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.