git-daemon: keep track of children
authorLinus Torvalds <torvalds@g5.osdl.org>
Sat, 16 Jul 2005 03:42:28 +0000 (20:42 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Sat, 16 Jul 2005 03:42:28 +0000 (20:42 -0700)
We don't want them as zombies, and eventually we'll want to limit their
number. Right now we just count them.

daemon.c

index 74a1934..e6fbab6 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -1,10 +1,24 @@
 #include "cache.h"
 #include "pkt-line.h"
+#include <signal.h>
+#include <sys/wait.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 
 static const char daemon_usage[] = "git-daemon [--inetd | --port=n]";
 
+/* We don't actually do anything about this yet */
+static int max_connections = 10;
+
+/*
+ * We count spawned/reaped separately, just to avoid any
+ * races when updating them from signals. The SIGCHLD handler
+ * will only update children_reaped, and the fork logic will
+ * only update children_spawned.
+ */
+static unsigned int children_spawned = 0;
+static unsigned int children_reaped = 0;
+
 static int upload(char *dir, int dirlen)
 {
        if (chdir(dir) < 0)
@@ -47,8 +61,24 @@ static int execute(void)
 
 static void handle(int incoming, struct sockaddr_in *addr, int addrlen)
 {
-       if (fork()) {
+       pid_t pid = fork();
+
+       if (pid) {
+               int active;
+
                close(incoming);
+               if (pid < 0)
+                       return;
+
+               active = ++children_spawned - children_reaped;
+               if (active > max_connections) {
+                       /*
+                        * Fixme! This is where you'd have to do something to
+                        * limit the number of children. Like killing off random
+                        * ones, or at least the ones that haven't even gotten
+                        * started yet.
+                        */
+               }
                return;
        }
 
@@ -58,11 +88,23 @@ static void handle(int incoming, struct sockaddr_in *addr, int addrlen)
        exit(execute());
 }
 
+static void child_handler(int signo)
+{
+       for (;;) {
+               if (waitpid(-1, NULL, WNOHANG) > 0) {
+                       children_reaped++;
+                       continue;
+               }
+               break;
+       }
+}
+
 static int serve(int port)
 {
        int sockfd;
        struct sockaddr_in addr;
 
+       signal(SIGCHLD, child_handler);
        sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
        if (sockfd < 0)
                die("unable to open socket (%s)", strerror(errno));