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

Re: [PATCH 3/3] Add sideband status report to git-archive protocol

From
Junio C Hamano <junkio@cox.net>
Date
Sep 12, 2006, 07:24 UTC
Message-ID
<7vzmd5eedk.fsf@assigned-by-dhcp.cox.net>
In-Reply-To
<45053BA2.6050502@innova-card.com>
Franck Bui-Huu <vagabon.xyz@gmail.com> writes:
> I get a lot of "Hmph, HUP?" messages when testing "git-archive
> --remote" command. One guess: this can be due to the fact that when
> the writer process exits, it first closes its fd but do not send a
> SIGCHLD signal right after to its parent.

It does not reproduce for me, but the code I have is obviously bogus in a few places.

 - When POLLHUP is set, it goes ahead and reads the file
   descriptor.  Worse yet, it does not check the return value of
   read() for errors when it does.
 - When we processed one POLLIN, we should just go back and see
   if any more data is available.  We can check if the child is
   still there when poll gave control back at us but without any
   actual input as you said.

I was uncomfortable letting waitpid() there to wait forever. When does poll() return? (1) we have data ready in which case we process; (2) the child somehow closed the pipe but without dying, which is an error in the child. In the latter case even not hanging in waitpid() and retrying the poll would not give any useful input so that would not help either.

So I think your patch is a correct fix, except that I think we should let the remote side know why we stopped talking to them instead of calling die() there.

We should also check when read() returns an error, so how about this on top of your patch?

diff --git a/builtin-upload-archive.c b/builtin-upload-archive.c
index 2ebe9a0..a53cfee 100644
--- a/builtin-upload-archive.c
+++ b/builtin-upload-archive.c
@@ -16,6 +16,9 @@ static const char upload_archive_usage[]
 static const char deadchild[] =
 "git-upload-archive: archiver died with error";
 
+static const char lostchild[] =
+"git-upload-archive: archiver process was lost";
+
 
 static int run_upload_archive(int argc, const char **argv, const char *prefix)
 {
@@ -73,6 +76,31 @@ static int run_upload_archive(int argc, 
 	return ar.write_archive(&ar.args);
 }
 
+static void error_clnt(const char *fmt, ...)
+{
+	char buf[1024];
+	va_list params;
+	int len;
+
+	va_start(params, fmt);
+	len = vsprintf(buf, fmt, params);
+	va_end(params);
+	send_sideband(1, 3, buf, len, LARGE_PACKET_MAX);
+	die("sent error to the client: %s", buf);
+}
+
+static void process_input(int child_fd, int band)
+{
+	char buf[16384];
+	ssize_t sz = read(child_fd, buf, sizeof(buf));
+	if (sz < 0) {
+		if (errno != EINTR)
+			error_clnt("read error: %s\n", strerror(errno));
+	}
+	else if (sz)
+		send_sideband(1, band, buf, sz, LARGE_PACKET_MAX);
+}
+
 int cmd_upload_archive(int argc, const char **argv, const char *prefix)
 {
 	pid_t writer;
@@ -112,8 +140,6 @@ int cmd_upload_archive(int argc, const c
 
 	while (1) {
 		struct pollfd pfd[2];
-		char buf[16384];
-		ssize_t sz;
 		int status;
 
 		pfd[0].fd = fd1[0];
@@ -128,26 +154,19 @@ int cmd_upload_archive(int argc, const c
 			}
 			continue;
 		}
-		if (pfd[0].revents & (POLLIN|POLLHUP)) {
+		if (pfd[0].revents & POLLIN)
 			/* Data stream ready */
-			sz = read(pfd[0].fd, buf, sizeof(buf));
-			send_sideband(1, 1, buf, sz, LARGE_PACKET_MAX);
-		}
-		if (pfd[1].revents & (POLLIN|POLLHUP)) {
+			process_input(pfd[0].fd, 1);
+		if (pfd[1].revents & POLLIN)
 			/* Status stream ready */
-			sz = read(pfd[1].fd, buf, sizeof(buf));
-			send_sideband(1, 2, buf, sz, LARGE_PACKET_MAX);
-		}
-
+			process_input(pfd[1].fd, 2);
 		if ((pfd[0].revents | pfd[1].revents) == POLLIN)
 			continue;
 
-		if (waitpid(writer, &status, 0) < 0) {
-			die("waitpid failed: %s", strerror(errno));
-		}
-		if (!WIFEXITED(status) || WEXITSTATUS(status) > 0)
-			send_sideband(1, 3, deadchild, strlen(deadchild),
-				      LARGE_PACKET_MAX);
+		if (waitpid(writer, &status, 0) < 0)
+			error_clnt("%s", lostchild);
+		else if (!WIFEXITED(status) || WEXITSTATUS(status) > 0)
+			error_clnt("%s", deadchild);
 		packet_flush(1);
 		break;
 	}
Previous: Franck Bui-HuuNext: Franck Bui-Huu
Message 17 of 28 in “archive: allow remote to have more formats than we understand.”
  1. 1/2 archive: allow remote to have more formats than we understand.Junio C Hamano, Sep 10, 2006
  2. 2/2 Add --verbose to git-archiveJunio C Hamano, Sep 10, 2006
  3. 1/3 Move sideband client side support into reusable form.Junio C Hamano, Sep 10, 2006
  4. Franck Bui-HuuSep 10, 2006
  5. Move sideband server side support into reusable form.Junio C Hamano, Sep 10, 2006
  6. 3/3 Add sideband status report to git-archive protocolJunio C Hamano, Sep 10, 2006
  7. git-upload-archive: add config option to allow only specified formatsRene Scharfe, Sep 10, 2006
  8. Rene ScharfeSep 10, 2006
  9. Junio C HamanoSep 10, 2006
  10. Rene ScharfeSep 11, 2006
  11. Jakub NarebskiSep 11, 2006
  12. Franck Bui-HuuSep 10, 2006
  13. Rene ScharfeSep 11, 2006
  14. Franck Bui-HuuSep 10, 2006
  15. Junio C HamanoSep 10, 2006
  16. Franck Bui-HuuSep 11, 2006
  17. Junio C HamanoSep 12, 2006
  18. Franck Bui-HuuSep 12, 2006
  19. Franck Bui-HuuSep 12, 2006
  20. connect.c: finish_connect(): allow null pid parameterFranck Bui-Huu, Sep 12, 2006
  21. Junio C HamanoSep 13, 2006
  22. Test return value of finish_connect()Franck Bui-Huu, Sep 13, 2006
  23. git_connect: change return type to pid_tFranck Bui-Huu, Sep 13, 2006
  24. Junio C HamanoSep 12, 2006
  25. Rene ScharfeSep 10, 2006
  26. Franck Bui-HuuSep 10, 2006
  27. Junio C HamanoSep 10, 2006
  28. Franck Bui-HuuSep 10, 2006

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.