X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=daemon.c;h=8dcde73200d1ddbc0dec0dbfdc2f4ff15047abd9;hb=f0e90716d47b429284702b75425a247c9fc41adb;hp=63cd12cd9c1909edbaab49aea066ff6fe03c3542;hpb=ea81e10ff4e31820407f4cb1b8ebd87de9e51737;p=git.git diff --git a/daemon.c b/daemon.c index 63cd12cd9..8dcde7320 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,22 +785,16 @@ 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; } + signal(SIGCHLD, child_handler); } static int set_reuse_addr(int sockfd) @@ -917,19 +936,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 +961,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) {