git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Carlo Marcelo Arenas Belón" <carenas@gmail.com>
To: git@vger.kernel.org
Cc: chris.torek@gmail.com, gitster@pobox.com,
	phillip.wood123@gmail.com,
	"Carlo Marcelo Arenas Belón" <carenas@gmail.com>
Subject: [RFC PATCH 2/2] daemon: poor man's pidfd like POC
Date: Thu, 26 Jun 2025 14:22:34 -0700	[thread overview]
Message-ID: <20250626212234.88570-3-carenas@gmail.com> (raw)
In-Reply-To: <20250626212234.88570-1-carenas@gmail.com>

Create a pipe for each child, and let the write side leak into
the children, then add the read side to the poll and wait for
the pipe to close (presumed to happen when the child is done).

There is no need to change the children code, since the OS (at
least in *NIX) will close all fds on termination.

This implementation is suboptimal, as it shouldn't need to
scan all children once a notification is received, but does so
to minimize changes.

Signed-off-by: Carlo Marcelo Arenas Belón <carenas@gmail.com>
---
 daemon.c | 74 +++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 52 insertions(+), 22 deletions(-)

diff --git a/daemon.c b/daemon.c
index d1be61fd57..c78556be97 100644
--- a/daemon.c
+++ b/daemon.c
@@ -811,9 +811,19 @@ static struct child {
 	struct sockaddr_storage address;
 } *firstborn;
 
-static void add_child(struct child_process *cld, struct sockaddr *addr, socklen_t addrlen)
+static void add_child(nfds_t *nfds, struct pollfd **pfd,
+			struct child_process *cld,
+			struct sockaddr *addr, socklen_t addrlen)
 {
 	struct child *newborn, **cradle;
+	struct pollfd newfd;
+	nfds_t size = *nfds;
+
+	newfd.fd = cld->parent_ipc_in;
+	newfd.events = POLL_HUP;
+	*nfds = size + 1;
+	REALLOC_ARRAY(*pfd, *nfds);
+	memcpy(*pfd + size, &newfd, sizeof(newfd));
 
 	CALLOC_ARRAY(newborn, 1);
 	live_children++;
@@ -846,10 +856,11 @@ static void kill_some_child(void)
 		}
 }
 
-static void check_dead_children(void)
+static void check_dead_children(nfds_t *nfds, struct pollfd *pfd, nfds_t base)
 {
 	int status;
 	pid_t pid;
+	nfds_t size = *nfds;
 
 	struct child **cradle, *blanket;
 	for (cradle = &firstborn; (blanket = *cradle);)
@@ -859,6 +870,20 @@ static void check_dead_children(void)
 				dead = " (with error)";
 			loginfo("[%"PRIuMAX"] Disconnected%s", (uintmax_t)pid, dead);
 
+			for (nfds_t i = base; i < size; i++)
+				if (pfd[i].fd == blanket->cld.parent_ipc_in) {
+					close(blanket->cld.parent_ipc_in);
+					size--;
+					if (size - i) {
+						MOVE_ARRAY(pfd + i,
+								pfd + i + 1,
+								size - i);
+					}
+
+					*nfds = size;
+					break;
+				}
+
 			/* remove the child */
 			*cradle = blanket->next;
 			live_children--;
@@ -869,14 +894,16 @@ static void check_dead_children(void)
 }
 
 static struct strvec cld_argv = STRVEC_INIT;
-static void handle(int incoming, struct sockaddr *addr, socklen_t addrlen)
+static void handle(int incoming, nfds_t *nfds, struct pollfd **pfd, nfds_t base,
+			struct sockaddr *addr, socklen_t addrlen)
 {
+	int ipc[2] = { -1, -1 };
 	struct child_process cld = CHILD_PROCESS_INIT;
 
 	if (max_connections && live_children >= max_connections) {
 		kill_some_child();
 		sleep(1);  /* give it some time to die */
-		check_dead_children();
+		check_dead_children(nfds, *pfd, base);
 		if (live_children >= max_connections) {
 			close(incoming);
 			logerror("Too many children, dropping connection");
@@ -902,24 +929,22 @@ static void handle(int incoming, struct sockaddr *addr, socklen_t addrlen)
 #endif
 	}
 
+#ifndef GIT_WINDOWS_NATIVE
+	pipe(ipc);
+	cld.parent_ipc_in = ipc[0];
+#endif
+
 	strvec_pushv(&cld.args, cld_argv.v);
 	cld.in = incoming;
 	cld.out = dup(incoming);
 
 	if (start_command(&cld))
 		logerror("unable to fork");
-	else
-		add_child(&cld, addr, addrlen);
-}
-
-static void child_handler(int signo UNUSED)
-{
-	/*
-	 * Otherwise empty handler because systemcalls will get interrupted
-	 * upon signal receipt
-	 * SysV needs the handler to be rearmed
-	 */
-	signal(SIGCHLD, child_handler);
+	else {
+		if (ipc[1] != -1)
+			close(ipc[1]);
+		add_child(nfds, pfd, &cld, addr, addrlen);
+	}
 }
 
 static int set_reuse_addr(int sockfd)
@@ -1121,6 +1146,7 @@ static void socksetup(struct string_list *listen_addr, int listen_port, struct s
 static int service_loop(struct socketlist *socklist)
 {
 	struct pollfd *pfd;
+	nfds_t nfds = socklist->nr;
 
 	CALLOC_ARRAY(pfd, socklist->nr);
 
@@ -1129,12 +1155,10 @@ static int service_loop(struct socketlist *socklist)
 		pfd[i].events = POLLIN;
 	}
 
-	signal(SIGCHLD, child_handler);
-
 	for (;;) {
-		check_dead_children();
+		size_t i;
 
-		if (poll(pfd, socklist->nr, -1) < 0) {
+		if (poll(pfd, nfds, -1) < 0) {
 			if (errno != EINTR) {
 				logerror("Poll failed, resuming: %s",
 				      strerror(errno));
@@ -1143,7 +1167,12 @@ static int service_loop(struct socketlist *socklist)
 			continue;
 		}
 
-		for (size_t i = 0; i < socklist->nr; i++) {
+		for (i = socklist->nr; i < nfds; i++) {
+			if (pfd[i].revents & POLLHUP)
+				check_dead_children(&nfds, pfd, socklist->nr);
+		}
+
+		for (i = 0; i < socklist->nr; i++) {
 			if (pfd[i].revents & POLLIN) {
 				union {
 					struct sockaddr sa;
@@ -1164,7 +1193,8 @@ static int service_loop(struct socketlist *socklist)
 						die_errno("accept returned");
 					}
 				}
-				handle(incoming, &ss.sa, sslen);
+				handle(incoming, &nfds, &pfd, socklist->nr,
+					&ss.sa, sslen);
 			}
 		}
 	}
-- 
2.39.5 (Apple Git-154)


  parent reply	other threads:[~2025-06-26 21:22 UTC|newest]

Thread overview: 70+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-24 14:08 [PATCH 0/3] daemon: explicitly allow EINTR during poll() Carlo Marcelo Arenas Belón via GitGitGadget
2025-06-24 14:08 ` [PATCH 1/3] compat/posix.h: track SA_RESTART fallback Carlo Marcelo Arenas Belón via GitGitGadget
2025-06-24 15:34   ` Junio C Hamano
2025-06-24 16:28   ` Junio C Hamano
2025-06-24 14:08 ` [PATCH 2/3] daemon: use sigaction() to install child_handler() Carlo Marcelo Arenas Belón via GitGitGadget
2025-06-24 15:37   ` Junio C Hamano
2025-06-24 22:29     ` Carlo Marcelo Arenas Belón
2025-06-24 23:27       ` Chris Torek
2025-06-24 16:20   ` Junio C Hamano
2025-06-24 21:28     ` Carlo Marcelo Arenas Belón
2025-06-24 21:32       ` Junio C Hamano
2025-06-24 14:08 ` [PATCH 3/3] daemon: explicitly allow EINTR during poll() Carlo Marcelo Arenas Belón via GitGitGadget
2025-06-24 14:33   ` Carlo Marcelo Arenas Belón
2025-06-24 15:43   ` Junio C Hamano
2025-06-25  7:35 ` [PATCH v2 0/3] " Carlo Marcelo Arenas Belón via GitGitGadget
2025-06-25  7:35   ` [PATCH v2 1/3] compat/posix.h: track SA_RESTART fallback Carlo Marcelo Arenas Belón via GitGitGadget
2025-06-25 16:07     ` Junio C Hamano
2025-06-25 22:24       ` Carlo Marcelo Arenas Belón
2025-06-26  0:33         ` Junio C Hamano
2025-06-26  1:35           ` Carlo Marcelo Arenas Belón
2025-06-26  0:45     ` Junio C Hamano
2025-06-25  7:35   ` [PATCH v2 2/3] daemon: use sigaction() to install child_handler() Carlo Marcelo Arenas Belón via GitGitGadget
2025-06-25 16:06     ` Junio C Hamano
2025-06-25 16:22       ` Junio C Hamano
2025-06-25  7:35   ` [PATCH v2 3/3] daemon: explicitly allow EINTR during poll() Carlo Marcelo Arenas Belón via GitGitGadget
2025-06-25 16:11     ` Junio C Hamano
2025-06-25  8:39   ` [PATCH v2 0/3] " Phillip Wood
2025-06-25 16:24     ` Junio C Hamano
2025-06-25 19:35       ` Phillip Wood
2025-06-26 18:24         ` [RFC PATCH] daemon: add a self pipe to trigger reaping of children Carlo Marcelo Arenas Belón
2025-06-26 21:22           ` [RFC PATCH 0/2] daemon: tracking childs without signals Carlo Marcelo Arenas Belón
2025-06-26 21:22             ` [RFC PATCH 1/2] run-command: add a pipe() write end to childs Carlo Marcelo Arenas Belón
2025-06-26 21:22             ` Carlo Marcelo Arenas Belón [this message]
2025-06-27  8:38           ` [RFC PATCH] daemon: add a self pipe to trigger reaping of children Phillip Wood
2025-06-28  6:19             ` Carlo Marcelo Arenas Belón
2025-07-01 13:38               ` Phillip Wood
2025-06-30 15:16             ` Junio C Hamano
2025-06-25 16:07   ` [PATCH v2 0/3] daemon: explicitly allow EINTR during poll() Junio C Hamano
2025-06-26  8:50     ` Carlo Marcelo Arenas Belón
2025-06-26  8:53   ` [PATCH v3 0/4] " Carlo Marcelo Arenas Belón via GitGitGadget
2025-06-26  8:53     ` [PATCH v3 1/4] compat/posix.h: track SA_RESTART fallback Carlo Marcelo Arenas Belón via GitGitGadget
2025-06-27  1:41       ` Junio C Hamano
2025-06-26  8:53     ` [PATCH v3 2/4] compat/mingw: allow sigaction(SIGCHLD) Carlo Marcelo Arenas Belón via GitGitGadget
2025-06-26 12:52       ` Phillip Wood
2025-06-26 13:15         ` Carlo Marcelo Arenas Belón
2025-06-26 13:56           ` Phillip Wood
2025-06-26 14:58             ` Carlo Marcelo Arenas Belón
2025-06-26 15:19               ` phillip.wood123
2025-06-26 20:09                 ` Carlo Marcelo Arenas Belón
2025-07-09 14:13                   ` Phillip Wood
2025-07-09 16:36                     ` Carlo Marcelo Arenas Belón
2025-06-26  8:53     ` [PATCH v3 3/4] daemon: use sigaction() to install child_handler() Carlo Marcelo Arenas Belón via GitGitGadget
2025-06-26 13:11       ` Phillip Wood
2025-06-26 15:33         ` Junio C Hamano
2025-06-26 16:36           ` Carlo Marcelo Arenas Belón
2025-06-26 18:04             ` Phillip Wood
2025-07-07 22:14               ` Junio C Hamano
2025-06-26  8:53     ` [PATCH v3 4/4] daemon: explicitly allow EINTR during poll() Carlo Marcelo Arenas Belón via GitGitGadget
2025-06-26 13:14       ` Phillip Wood
2025-07-09 14:12     ` [PATCH v3 0/4] " Phillip Wood
2025-07-09 17:04       ` Carlo Marcelo Arenas Belón
2025-07-10 19:45     ` [PATCH v4 0/2] " Carlo Marcelo Arenas Belón via GitGitGadget
2025-07-10 19:45       ` [PATCH v4 1/2] compat/mingw: allow sigaction(SIGCHLD) Carlo Marcelo Arenas Belón via GitGitGadget
2025-07-10 21:38         ` Eric Sunshine
2025-07-10 19:45       ` [PATCH v4 2/2] daemon: use sigaction() to install child_handler() Carlo Marcelo Arenas Belón via GitGitGadget
2025-07-10 21:26       ` [PATCH v4 0/2] daemon: explicitly allow EINTR during poll() Junio C Hamano
2025-07-10 23:18         ` Carlo Arenas
2025-07-11 13:14         ` Phillip Wood
2025-07-14 21:52           ` Junio C Hamano
2025-07-15  9:29             ` Phillip Wood

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250626212234.88570-3-carenas@gmail.com \
    --to=carenas@gmail.com \
    --cc=chris.torek@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=phillip.wood123@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).