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

[PATCH 2/5] Use start_command() in git_connect() instead of explicit fork/exec.

From
Johannes Sixt <johannes.sixt@telecom.at>
Date
Sep 30, 2007, 20:09 UTC
Message-ID
<1191183001-5368-3-git-send-email-johannes.sixt@telecom.at>
In-Reply-To
<1191183001-5368-2-git-send-email-johannes.sixt@telecom.at>

The child process handling is delegated to start_command() and finish_command().

Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>
---
 connect.c |  104 ++++++++++++++++++++++++++++--------------------------------
 1 files changed, 49 insertions(+), 55 deletions(-)
diff --git a/connect.c b/connect.c
index f6dcab9..29fd431 100644
--- a/connect.c
+++ b/connect.c
@@ -482,11 +482,12 @@ struct child_process *git_connect(int fd[2], char *url,
 	char *host, *path = url;
 	char *end;
 	int c;
-	int pipefd[2][2];
 	struct child_process *chld;
 	enum protocol protocol = PROTO_LOCAL;
 	int free_path = 0;
 	char *port = NULL;
+	const char **arg;
+	struct strbuf cmd;
 
 	/* Without this we cannot rely on waitpid() to tell
 	 * what happened to our children.
@@ -572,72 +573,65 @@ struct child_process *git_connect(int fd[2], char *url,
 		return NULL;
 	}
 
-	if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0)
-		die("unable to create pipe pair for communication");
 	chld = xcalloc(1, sizeof(*chld));
-	chld->pid = fork();
-	if (chld->pid < 0)
-		die("unable to fork");
-	if (!chld->pid) {
-		struct strbuf cmd;
-
-		strbuf_init(&cmd, MAX_CMD_LEN);
-		strbuf_addstr(&cmd, prog);
-		strbuf_addch(&cmd, ' ');
-		sq_quote_buf(&cmd, path);
-		if (cmd.len >= MAX_CMD_LEN)
-			die("command line too long");
-
-		dup2(pipefd[1][0], 0);
-		dup2(pipefd[0][1], 1);
-		close(pipefd[0][0]);
-		close(pipefd[0][1]);
-		close(pipefd[1][0]);
-		close(pipefd[1][1]);
-		if (protocol == PROTO_SSH) {
-			const char *ssh, *ssh_basename;
-			ssh = getenv("GIT_SSH");
-			if (!ssh) ssh = "ssh";
-			ssh_basename = strrchr(ssh, '/');
-			if (!ssh_basename)
-				ssh_basename = ssh;
-			else
-				ssh_basename++;
 
-			if (!port)
-				execlp(ssh, ssh_basename, host, cmd.buf, NULL);
-			else
-				execlp(ssh, ssh_basename, "-p", port, host,
-				       cmd.buf, NULL);
+	strbuf_init(&cmd, MAX_CMD_LEN);
+	strbuf_addstr(&cmd, prog);
+	strbuf_addch(&cmd, ' ');
+	sq_quote_buf(&cmd, path);
+	if (cmd.len >= MAX_CMD_LEN)
+		die("command line too long");
+
+	chld->in = chld->out = -1;
+	chld->argv = arg = xcalloc(6, sizeof(*arg));
+	if (protocol == PROTO_SSH) {
+		const char *ssh = getenv("GIT_SSH");
+		if (!ssh) ssh = "ssh";
+
+		*arg++ = ssh;
+		if (port) {
+			*arg++ = "-p";
+			*arg++ = port;
 		}
-		else {
-			unsetenv(ALTERNATE_DB_ENVIRONMENT);
-			unsetenv(DB_ENVIRONMENT);
-			unsetenv(GIT_DIR_ENVIRONMENT);
-			unsetenv(GIT_WORK_TREE_ENVIRONMENT);
-			unsetenv(GRAFT_ENVIRONMENT);
-			unsetenv(INDEX_ENVIRONMENT);
-			execlp("sh", "sh", "-c", cmd.buf, NULL);
-		}
-		die("exec failed");
+		*arg++ = host;
+	}
+	else {
+		/* remove these from the environment */
+		const char *env[] = {
+			ALTERNATE_DB_ENVIRONMENT,
+			DB_ENVIRONMENT,
+			GIT_DIR_ENVIRONMENT,
+			GIT_WORK_TREE_ENVIRONMENT,
+			GRAFT_ENVIRONMENT,
+			INDEX_ENVIRONMENT,
+			NULL
+		};
+		chld->env = env;
+		*arg++ = "sh";
+		*arg++ = "-c";
 	}
-	fd[0] = pipefd[0][0];
-	fd[1] = pipefd[1][1];
-	close(pipefd[0][1]);
-	close(pipefd[1][0]);
+	*arg++ = cmd.buf;
+	*arg = NULL;
+
+	if (start_command(chld))
+		die("unable to fork");
+
+	fd[0] = chld->out; /* read from child's stdout */
+	fd[1] = chld->in;  /* write to child's stdin */
 	if (free_path)
 		free(path);
+	strbuf_release(&cmd);
 	return chld;
 }
 
 int finish_connect(struct child_process *chld)
 {
+	int code;
 	if (chld == NULL)
 		return 0;
 
-	while (waitpid(chld->pid, NULL, 0) < 0) {
-		if (errno != EINTR)
-			return -1;
-	}
-	return 0;
+	code = finish_command(chld);
+	free(chld->argv);
+	free(chld);
+	return code;
 }
-- 
1.5.3.3.1134.gee562
Previous: Johannes SixtNext: Johannes Sixt
Message 3 of 30 in “fork/exec removal series”
  1. 0/5 fork/exec removal seriesJohannes Sixt, Sep 30, 2007
  2. 1/5 Change git_connect() to return a struct child_process instead of a pid_t.Johannes Sixt, Sep 30, 2007
  3. 2/5 Use start_command() in git_connect() instead of explicit fork/exec.Johannes Sixt, Sep 30, 2007
  4. 3/5 Use start_command() to run the filter instead of explicit fork/exec.Johannes Sixt, Sep 30, 2007
  5. 4/5 Use run_command() to spawn external diff programs instead of fork/exec.Johannes Sixt, Sep 30, 2007
  6. 5/5 Use start_comand() in builtin-fetch-pack.c instead of explicit fork/exec.Johannes Sixt, Sep 30, 2007
  7. Johannes SchindelinSep 30, 2007
  8. Johannes SchindelinSep 30, 2007
  9. Junio C HamanoSep 30, 2007
  10. Johannes SixtSep 30, 2007
  11. 0/5 fork/exec removal seriesJohannes Sixt, Oct 3, 2007
  12. 1/5 Change git_connect() to return a struct child_process instead of a pid_t.Johannes Sixt, Oct 3, 2007
  13. 2/5 Use start_command() in git_connect() instead of explicit fork/exec.Johannes Sixt, Oct 3, 2007
  14. 3/5 Use start_command() to run the filter instead of explicit fork/exec.Johannes Sixt, Oct 3, 2007
  15. 4/5 Use run_command() to spawn external diff programs instead of fork/exec.Johannes Sixt, Oct 3, 2007
  16. 5/5 Use start_comand() in builtin-fetch-pack.c instead of explicit fork/exec.Johannes Sixt, Oct 3, 2007
  17. Junio C HamanoOct 4, 2007
  18. Johannes SixtOct 4, 2007
  19. Johannes SixtOct 4, 2007
  20. Johannes SixtOct 1, 2007
  21. Junio C HamanoOct 1, 2007
  22. Johannes SixtOct 1, 2007
  23. Junio C HamanoOct 2, 2007
  24. Johannes SchindelinSep 30, 2007
  25. Junio C HamanoSep 30, 2007
  26. Johannes SchindelinSep 30, 2007
  27. Johannes SixtSep 30, 2007
  28. Johannes SchindelinSep 30, 2007
  29. Johannes SixtOct 1, 2007
  30. David KastrupOct 1, 2007

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.