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

[RFC PATCH 1/2] Report exec errors from run-command

From
ILIlari Liusvaara <ilari.liusvaara@elisanet.fi>
Date
Dec 24, 2009, 17:49 UTC
Message-ID
<1261676971-3285-2-git-send-email-ilari.liusvaara@elisanet.fi>
In-Reply-To
<1261676971-3285-1-git-send-email-ilari.liusvaara@elisanet.fi>

Previously run-command was unable to report errors happening in exec call. Change it to pass errno from failed exec to errno value at return.

The errno value passing can be done by opening close-on-exec pipe and piping the error code through in case of failure. In case of success, close-on-exec closes the pipe on successful exec and parent process gets end of file on read.

Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
 run-command.c |   72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 69 insertions(+), 3 deletions(-)
diff --git a/run-command.c b/run-command.c
index cf2d8f7..d334d0f 100644
--- a/run-command.c
+++ b/run-command.c
@@ -76,9 +76,60 @@ fail_pipe:
 	trace_argv_printf(cmd->argv, "trace: run_command:");
 
 #ifndef WIN32
+{
+	int report_pipe[2] = {-1, -1};
+
+	if (pipe(report_pipe) < 0)
+		warning("Can't open pipe for exec status report: %s\n",
+			strerror(errno));
+
 	fflush(NULL);
 	cmd->pid = fork();
-	if (!cmd->pid) {
+	if (cmd->pid > 0) {
+		int r = 0, ret;
+		while(close(report_pipe[1]) < 0 && errno != EBADF);
+read_again:
+		if (report_pipe[0] > 0)
+			r = read(report_pipe[0], &ret, sizeof(ret));
+		if (r < 0 && (errno == EAGAIN || errno == EINTR ||
+			errno == EWOULDBLOCK))
+			goto read_again;
+		else if (r < 0)
+			warning("Can't read exec status report: %s\n",
+				strerror(errno));
+		else if (r == 0)
+			;
+		else if (r < sizeof(ret))
+			warning("Received incomplete exec status report.\n");
+		else {
+			failed_errno = ret;
+			/*
+			 * Clean up the process that did the failed execution
+			 * so no zombies remain.
+			 */
+wait_again:
+			r = waitpid(cmd->pid, &ret, 0);
+			if (r < 0 && errno != ECHILD)
+				goto wait_again;
+			cmd->pid = -1;
+		}
+	} else if (!cmd->pid) {
+		int r = 0;
+		int flags;
+		while(close(report_pipe[0]) < 0 && errno != EBADF);
+
+		flags = fcntl(report_pipe[1], F_GETFD);
+		if (flags < 0)
+			r = -1;
+		flags |= FD_CLOEXEC;
+		r = (r || fcntl(report_pipe[1], F_SETFD, flags));
+		if (r) {
+			warning("Can't FD_CLOEXEC pipe for exec status "
+				"report: %s\n", strerror(errno));
+			while(close(report_pipe[1]) < 0 && errno != EBADF);
+			report_pipe[1] = -1;
+		}
+
 		if (cmd->no_stdin)
 			dup_devnull(0);
 		else if (need_in) {
@@ -126,13 +177,28 @@ fail_pipe:
 		} else {
 			execvp(cmd->argv[0], (char *const*) cmd->argv);
 		}
+		failed_errno = errno;
+
 		trace_printf("trace: exec '%s' failed: %s\n", cmd->argv[0],
 				strerror(errno));
+
+		r = 0;
+write_again:
+		if (report_pipe[1] >= 0)
+			r = write(report_pipe[1], &failed_errno,
+				sizeof(failed_errno));
+		if (r < 0 && (errno == EAGAIN || errno == EINTR ||
+			errno == EWOULDBLOCK))
+			goto write_again;
+		else if (r < 0)
+			warning("Can't write exec status report: %s\n",
+				strerror(errno));
+
 		exit(127);
-	}
-	if (cmd->pid < 0)
+	} else if (cmd->pid < 0)
 		error("cannot fork() for %s: %s", cmd->argv[0],
 			strerror(failed_errno = errno));
+}
 #else
 {
 	int s0 = -1, s1 = -1, s2 = -1;	/* backups of stdin, stdout, stderr */
-- 
1.6.6.3.gaa2e1
Previous: Ilari LiusvaaraNext: Junio C Hamano
Message 2 of 11 in “Report remote helper exec failures”
  1. 0/2 Report remote helper exec failuresIlari Liusvaara, Dec 24, 2009
  2. 1/2 Report exec errors from run-commandIlari Liusvaara, Dec 24, 2009
  3. Junio C HamanoDec 25, 2009
  4. Junio C HamanoDec 25, 2009
  5. Junio C HamanoDec 25, 2009
  6. Ilari LiusvaaraDec 25, 2009
  7. Johannes SixtDec 25, 2009
  8. Ilari LiusvaaraDec 25, 2009
  9. 2/2 Improve transport helper exec failure reportingIlari Liusvaara, Dec 24, 2009
  10. Junio C HamanoDec 25, 2009
  11. Ilari LiusvaaraDec 25, 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.