1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-10-28 12:59:41 +01:00

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>
This commit is contained in:
Stephen R. van den Berg 2008-08-14 20:02:20 +02:00 committed by Junio C Hamano
parent 6a992e9e1d
commit 695605b508

View file

@ -16,7 +16,6 @@
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"
@ -680,6 +679,21 @@ static void check_dead_children(void)
{
unsigned spawned, reaped, deleted;
for (;;) {
int status;
pid_t pid = waitpid(-1, &status, WNOHANG);
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;
continue;
}
break;
}
spawned = children_spawned;
reaped = children_reaped;
deleted = children_deleted;
@ -760,21 +774,10 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen)
static void child_handler(int signo)
{
for (;;) {
int status;
pid_t pid = waitpid(-1, &status, WNOHANG);
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;
write(child_handler_pipe[1], &status, 1);
continue;
}
break;
}
/* Otherwise empty handler because systemcalls will get interrupted
* upon signal receipt
* SysV needs the handler to be rearmed
*/
signal(SIGCHLD, child_handler);
}
@ -917,24 +920,21 @@ static int service_loop(int socknum, int *socklist)
struct pollfd *pfd;
int i;
if (pipe(child_handler_pipe) < 0)
die ("Could not set up pipe for child handler");
pfd = xcalloc(socknum + 1, sizeof(struct pollfd));
pfd = xcalloc(socknum, 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, -1) < 0) {
check_dead_children();
if (poll(pfd, socknum, -1) < 0) {
if (errno != EINTR) {
logerror("Poll failed, resuming: %s",
strerror(errno));
@ -942,10 +942,6 @@ 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) {
@ -1036,11 +1032,6 @@ int main(int argc, char **argv)
gid_t gid = 0;
int i;
/* Without this we cannot rely on waitpid() to tell
* what happened to our children.
*/
signal(SIGCHLD, SIG_DFL);
for (i = 1; i < argc; i++) {
char *arg = argv[i];