git-daemon: Simplify dead-children reaping logic
Move almost all code out of the child_handler() into check_dead_children(). The fact that systemcalls get interrupted by signals allows us to make the SIGCHLD signal handler almost a no-op by simply running check_dead_children() right before waiting on poll(). In case some systems do not interrupt systemcalls upon signal receipt, all zombies will eventually be collected before the next poll() cycle. Signed-off-by: Stephen R. van den Berg <srb@cuci.nl> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Stephen R. van den Berg committed
Aug 14, 2008 at 20:02 UTC
695605b5080e1957bd9dab1fed35a7fee9814297
1 file changed
+23
-32
daemon.c
+23
-32
@@ -16,7 +16,6 @@
16
static int log_syslog;
17
static int verbose;
18
static int reuseaddr;
19
-static int child_handler_pipe[2];
19
20
static const char daemon_usage[] =
21
"git daemon [--verbose] [--syslog] [--export-all]\n"
@@ -680,6 +679,21 @@ static void check_dead_children(void)
679
{
680
unsigned spawned, reaped, deleted;
681
682
+ for (;;) {
683
+ int status;
684
+ pid_t pid = waitpid(-1, &status, WNOHANG);
685
+
686
+ if (pid > 0) {
687
+ unsigned reaped = children_reaped;
688
+ if (!WIFEXITED(status) || WEXITSTATUS(status) > 0)
689
+ pid = -pid;
690
+ dead_child[reaped % MAX_CHILDREN] = pid;
691
+ children_reaped = reaped + 1;
692
+ continue;
693
+ }
694
+ break;
695
+ }
696
+
697
spawned = children_spawned;
698
reaped = children_reaped;
699
deleted = children_deleted;
@@ -760,21 +774,10 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen)
774
775
static void child_handler(int signo)
776
{
763
- for (;;) {
764
- int status;
765
- pid_t pid = waitpid(-1, &status, WNOHANG);
766
-
767
- if (pid > 0) {
768
- unsigned reaped = children_reaped;
769
- if (!WIFEXITED(status) || WEXITSTATUS(status) > 0)
770
- pid = -pid;
771
- dead_child[reaped % MAX_CHILDREN] = pid;
772
- children_reaped = reaped + 1;
773
- write(child_handler_pipe[1], &status, 1);
774
- continue;
775
- }
776
- break;
777
- }
777
+ /* Otherwise empty handler because systemcalls will get interrupted
778
+ * upon signal receipt
779
+ * SysV needs the handler to be rearmed
780
+ */
781
signal(SIGCHLD, child_handler);
782
}
783
@@ -917,24 +920,21 @@ static int service_loop(int socknum, int *socklist)
920
struct pollfd *pfd;
921
int i;
922
920
- if (pipe(child_handler_pipe) < 0)
921
- die ("Could not set up pipe for child handler");
922
-
923
- pfd = xcalloc(socknum + 1, sizeof(struct pollfd));
923
+ pfd = xcalloc(socknum, sizeof(struct pollfd));
924
925
for (i = 0; i < socknum; i++) {
926
pfd[i].fd = socklist[i];
927
pfd[i].events = POLLIN;
928
}
929
- pfd[socknum].fd = child_handler_pipe[0];
930
- pfd[socknum].events = POLLIN;
929
930
signal(SIGCHLD, child_handler);
931
932
for (;;) {
933
int i;
934
937
- if (poll(pfd, socknum + 1, -1) < 0) {
935
+ check_dead_children();
936
+
937
+ if (poll(pfd, socknum, -1) < 0) {
938
if (errno != EINTR) {
939
logerror("Poll failed, resuming: %s",
940
strerror(errno));
@@ -942,10 +942,6 @@ static int service_loop(int socknum, int *socklist)
942
}
943
continue;
944
}
945
- if (pfd[socknum].revents & POLLIN) {
946
- read(child_handler_pipe[0], &i, 1);
947
- check_dead_children();
948
- }
945
946
for (i = 0; i < socknum; i++) {
947
if (pfd[i].revents & POLLIN) {
@@ -1036,11 +1032,6 @@ int main(int argc, char **argv)
1032
gid_t gid = 0;
1033
int i;
1034
1039
- /* Without this we cannot rely on waitpid() to tell
1040
- * what happened to our children.
1041
- */
1042
- signal(SIGCHLD, SIG_DFL);
1043
-
1035
for (i = 1; i < argc; i++) {
1036
char *arg = argv[i];
1037