X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=daemon.c;h=4540e8df5ab8bc8ff66549144d7db2928e12199b;hb=c94c8e5ff63728a60494cbbcb28d5045584a997b;hp=63cd12cd9c1909edbaab49aea066ff6fe03c3542;hpb=bc9c3e0b932c5e14de749e07f5045197e7d6cd76;p=git.git diff --git a/daemon.c b/daemon.c index 63cd12cd9..4540e8df5 100644 --- a/daemon.c +++ b/daemon.c @@ -16,9 +16,10 @@ static int log_syslog; static int verbose; static int reuseaddr; +static int child_handler_pipe[2]; static const char daemon_usage[] = -"git-daemon [--verbose] [--syslog] [--export-all]\n" +"git daemon [--verbose] [--syslog] [--export-all]\n" " [--timeout=n] [--init-timeout=n] [--strict-paths]\n" " [--base-path=path] [--base-path-relaxed]\n" " [--user-path | --user-path=path]\n" @@ -694,23 +695,47 @@ static void kill_some_children(int signo, unsigned start, unsigned stop) } } +static void check_dead_children(void) +{ + unsigned spawned, reaped, deleted; + + spawned = children_spawned; + reaped = children_reaped; + deleted = children_deleted; + + while (deleted < reaped) { + pid_t pid = dead_child[deleted % MAX_CHILDREN]; + const char *dead = pid < 0 ? " (with error)" : ""; + + if (pid < 0) + pid = -pid; + + /* XXX: Custom logging, since we don't wanna getpid() */ + if (verbose) { + if (log_syslog) + syslog(LOG_INFO, "[%d] Disconnected%s", + pid, dead); + else + fprintf(stderr, "[%d] Disconnected%s\n", + pid, dead); + } + remove_child(pid, deleted, spawned); + deleted++; + } + children_deleted = deleted; +} + static void check_max_connections(void) { for (;;) { int active; - unsigned spawned, reaped, deleted; + unsigned spawned, deleted; + + check_dead_children(); spawned = children_spawned; - reaped = children_reaped; deleted = children_deleted; - while (deleted < reaped) { - pid_t pid = dead_child[deleted % MAX_CHILDREN]; - remove_child(pid, deleted, spawned); - deleted++; - } - children_deleted = deleted; - active = spawned - deleted; if (active <= max_connections) break; @@ -760,18 +785,11 @@ static void child_handler(int signo) if (pid > 0) { unsigned reaped = children_reaped; + if (!WIFEXITED(status) || WEXITSTATUS(status) > 0) + pid = -pid; dead_child[reaped % MAX_CHILDREN] = pid; children_reaped = reaped + 1; - /* XXX: Custom logging, since we don't wanna getpid() */ - if (verbose) { - const char *dead = ""; - if (!WIFEXITED(status) || WEXITSTATUS(status) > 0) - dead = " (with error)"; - if (log_syslog) - syslog(LOG_INFO, "[%d] Disconnected%s", pid, dead); - else - fprintf(stderr, "[%d] Disconnected%s\n", pid, dead); - } + write(child_handler_pipe[1], &status, 1); continue; } break; @@ -917,19 +935,24 @@ static int service_loop(int socknum, int *socklist) struct pollfd *pfd; int i; - pfd = xcalloc(socknum, sizeof(struct pollfd)); + if (pipe(child_handler_pipe) < 0) + die ("Could not set up pipe for child handler"); + + pfd = xcalloc(socknum + 1, sizeof(struct pollfd)); for (i = 0; i < socknum; i++) { pfd[i].fd = socklist[i]; pfd[i].events = POLLIN; } + pfd[socknum].fd = child_handler_pipe[0]; + pfd[socknum].events = POLLIN; signal(SIGCHLD, child_handler); for (;;) { int i; - if (poll(pfd, socknum, -1) < 0) { + if (poll(pfd, socknum + 1, -1) < 0) { if (errno != EINTR) { error("poll failed, resuming: %s", strerror(errno)); @@ -937,6 +960,10 @@ static int service_loop(int socknum, int *socklist) } continue; } + if (pfd[socknum].revents & POLLIN) { + read(child_handler_pipe[0], &i, 1); + check_dead_children(); + } for (i = 0; i < socknum; i++) { if (pfd[i].revents & POLLIN) {