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

Re: Funny: git -p submodule summary

From
Jeff King <peff@peff.net>
Date
Jan 9, 2009, 09:48 UTC
Message-ID
<20090109094843.GA4056@coredump.intra.peff.net>
In-Reply-To
<20090109092250.GA1809@coredump.intra.peff.net>
On Fri, Jan 09, 2009 at 04:22:50AM -0500, Jeff King wrote:
Show 7 quoted lines
> So I think to do things right, we have to be even more complicated. When
> we spawn the pager, we keep git as a single process. We register the
> atexit() handler to wait for the pager, and intercept any death signals
> to do the same. Then, if we are running a builtin, it is business as
> usual. But if we want to exec something, instead we have to actually
> spawn into the three-process form. Meaning we have to use run_command to
> start it, and then wait for it and the pager to return.

Actually, this turned out to be quite a small patch. It fixes the problem you were seeing, and it should work on Windows. It incurs an extra fork() for every dashed-external that we try.

There is a little noise in the patch, so let me highlight the three things that are happening (a "real" patch should break this into three patches in a series):

  1. The noise is from renaming the static run_command, which conflicts
     with the definition in run_command.h
  2. Substituting run_command for execvp.
  3. run_command needs to signal "I couldn't exec this" as opposed to
     other errors, since we care about the difference here. I do this
     here with exit(127), but probably we should recognize this in
     wait_or_whine and hand out the same error code for posix and mingw
     platforms.

As for the extra fork, we could do away with it if we scanned the path looking for the external before just exec'ing it. I think this is better in the long run anyway, because then we can do other setup specific to running an external command (I don't remember the details, but I ran afoul of this when I was doing pager stuff a while ago).

Patch is below.
---
diff --git a/git.c b/git.c
index ecc8fad..fa946b9 100644
--- a/git.c
+++ b/git.c
@@ -2,6 +2,7 @@
 #include "exec_cmd.h"
 #include "cache.h"
 #include "quote.h"
+#include "run-command.h"
 
 const char git_usage_string[] =
 	"git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]";
@@ -219,7 +220,7 @@ struct cmd_struct {
 	int option;
 };
 
-static int run_command(struct cmd_struct *p, int argc, const char **argv)
+static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
 {
 	int status;
 	struct stat st;
@@ -384,7 +385,7 @@ static void handle_internal_command(int argc, const char **argv)
 		struct cmd_struct *p = commands+i;
 		if (strcmp(p->cmd, cmd))
 			continue;
-		exit(run_command(p, argc, argv));
+		exit(run_builtin(p, argc, argv));
 	}
 }
 
@@ -392,6 +393,7 @@ static void execv_dashed_external(const char **argv)
 {
 	struct strbuf cmd = STRBUF_INIT;
 	const char *tmp;
+	int status;
 
 	strbuf_addf(&cmd, "git-%s", argv[0]);
 
@@ -406,8 +408,13 @@ static void execv_dashed_external(const char **argv)
 
 	trace_argv_printf(argv, "trace: exec:");
 
-	/* execvp() can only ever return if it fails */
-	execvp(cmd.buf, (char **)argv);
+	/*
+	 * if we failed because the command was not found, it is
+	 * OK to return. Otherwise, we just pass along the status code.
+	 */
+	status = run_command_v_opt(argv, 0);
+	if (status != 127 && status != -ERR_RUN_COMMAND_FORK)
+		exit(-status);
 
 	trace_printf("trace: exec failed: %s\n", strerror(errno));
 
diff --git a/run-command.c b/run-command.c
index c90cdc5..539609e 100644
--- a/run-command.c
+++ b/run-command.c
@@ -118,7 +118,7 @@ int start_command(struct child_process *cmd)
 		} else {
 			execvp(cmd->argv[0], (char *const*) cmd->argv);
 		}
-		die("exec %s failed.", cmd->argv[0]);
+		exit(127);
 	}
 #else
 	int s0 = -1, s1 = -1, s2 = -1;	/* backups of stdin, stdout, stderr */
Previous: Jeff KingNext: Johannes Sixt
Message 5 of 41 in “Funny: git -p submodule summary”
  1. Johannes SchindelinJan 8, 2009
  2. Johannes SchindelinJan 8, 2009
  3. Jeff KingJan 9, 2009
  4. Jeff KingJan 9, 2009
  5. Jeff KingJan 9, 2009
  6. Johannes SixtJan 9, 2009
  7. Jeff KingJan 9, 2009
  8. Johannes SixtJan 9, 2009
  9. Jeff KingJan 9, 2009
  10. Jeff KingJan 11, 2009
  11. 1/4 Makefile: clean up TEST_PROGRAMS definitionJeff King, Jan 11, 2009
  12. 2/4 chain kill signals for cleanup functionsJeff King, Jan 11, 2009
  13. Jeff KingJan 11, 2009
  14. 3/4 refactor signal handling for cleanup functionsJeff King, Jan 11, 2009
  15. 4/4 pager: do wait_for_pager on signal deathJeff King, Jan 11, 2009
  16. Junio C HamanoJan 11, 2009
  17. Johannes SixtJan 12, 2009
  18. Jeff KingJan 12, 2009
  19. Johannes SixtJan 12, 2009
  20. Jeff KingJan 12, 2009
  21. Johannes SixtJan 12, 2009
  22. Junio C HamanoJan 9, 2009
  23. Jeff KingJan 9, 2009
  24. Junio C HamanoJan 9, 2009
  25. 0/3 fix "Funny: git -p submodule summary"Jeff King, Jan 27, 2009
  26. 1/3 git: s/run_command/run_builtin/Jeff King, Jan 27, 2009
  27. 2/3 run_command: handle missing command errors more gracefullyJeff King, Jan 27, 2009
  28. 3/3 git: use run_command to execute dashed externalsJeff King, Jan 27, 2009
  29. Johannes SixtJan 27, 2009
  30. Jeff KingJan 27, 2009
  31. Johannes SixtJan 27, 2009
  32. Jeff KingJan 28, 2009
  33. Johannes SchindelinJan 27, 2009
  34. Jeff KingJan 28, 2009
  35. 1/4 git: s/run_command/run_builtin/Jeff King, Jan 28, 2009
  36. 2/4 run_command: handle missing command errors more gracefullyJeff King, Jan 28, 2009
  37. 3/4 run-command: help callers distinguish errorsJeff King, Jan 28, 2009
  38. Jeff KingJan 28, 2009
  39. Jeff KingJan 28, 2009
  40. 4/4 git: use run_command to execute dashed externalsJeff King, Jan 28, 2009
  41. Junio C HamanoJan 28, 2009

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.