ajp-wsgi-py3.0

changeset 101:ff02e95cfc95

Major simplification: use single pipe pair between parent and all children. Also fix descriptor leaks.
author Allan Saddi <allan@saddi.com>
date Sat, 15 Jan 2011 02:29:39 -0800
parents b846e560aa63
children 456a55da82a9
files main.c
diffstat 1 files changed, 16 insertions(+), 77 deletions(-) [+]
line diff
     1.1 --- a/main.c	Sat Jan 15 02:09:01 2011 -0800
     1.2 +++ b/main.c	Sat Jan 15 02:29:39 2011 -0800
     1.3 @@ -82,14 +82,8 @@
     1.4    struct sockaddr_in addr;
     1.5  };
     1.6  
     1.7 -/* For tracking pipes associated with each child */
     1.8 -struct childPipeData {
     1.9 -  struct childPipeData *next, *prev;
    1.10 -  pid_t pid;
    1.11 -  int fd;
    1.12 -};
    1.13 -
    1.14 -struct childPipeData childPipeHead, childPipeTail;
    1.15 +/* Pipe shared between parent and children to detect if parent dies */
    1.16 +static int pipefds[2]; /* pipefds[0] is child, pipefds[1] is parent */
    1.17  
    1.18  /* Simple wrapper around strerror */
    1.19  static void
    1.20 @@ -218,52 +212,6 @@
    1.21    pthread_mutex_unlock(&threadCountMutex);
    1.22  }
    1.23  
    1.24 -/* Keep track of a child process and its pipe */
    1.25 -static void
    1.26 -trackChild(pid_t child, int fd)
    1.27 -{
    1.28 -  struct childPipeData *cpd;
    1.29 -
    1.30 -  if ((cpd = malloc(sizeof(*cpd))) == NULL) {
    1.31 -    myperror("malloc");
    1.32 -    exit(2);
    1.33 -  }
    1.34 -
    1.35 -  cpd->pid = child;
    1.36 -  cpd->fd = fd;
    1.37 -
    1.38 -  /* Add to tail of list */
    1.39 -  childPipeTail.prev->next = cpd;
    1.40 -  cpd->prev = childPipeTail.prev;
    1.41 -
    1.42 -  cpd->next = &childPipeTail;
    1.43 -  childPipeTail.prev = cpd;
    1.44 -}
    1.45 -
    1.46 -/* Forget a child process and close its pipe */
    1.47 -static void
    1.48 -forgetChild(pid_t child)
    1.49 -{
    1.50 -  struct childPipeData *cpd = childPipeHead.next;
    1.51 -
    1.52 -  while (cpd->next) {
    1.53 -    if (cpd->pid == child) {
    1.54 -      /* Found it, close the socket */
    1.55 -      close(cpd->fd);
    1.56 -
    1.57 -      /* Unlink node from list */
    1.58 -      cpd->prev->next = cpd->next;
    1.59 -      cpd->next->prev = cpd->prev;
    1.60 -
    1.61 -      /* Free node */
    1.62 -      free(cpd);
    1.63 -      return;
    1.64 -    }
    1.65 -
    1.66 -    cpd = cpd->next;
    1.67 -  }
    1.68 -}
    1.69 -
    1.70  /* Connection handoff for processes */
    1.71  static void
    1.72  procHandoff(struct clientData *cd)
    1.73 @@ -273,29 +221,19 @@
    1.74      free(cd);
    1.75    }
    1.76    else {
    1.77 -    pid_t child;
    1.78 -    int p[2]; /* p[0] is child, p[1] is parent */
    1.79      int fd, fd_max;
    1.80  
    1.81 -    /* Create pipe so child knows when parent dies */
    1.82 -    if (pipe(p) == -1) {
    1.83 -      myperror("pipe");
    1.84 -      exit(2);
    1.85 -    }
    1.86 -
    1.87 -    switch ((child = fork())) {
    1.88 +    switch (fork()) {
    1.89      case -1:
    1.90        /* error */
    1.91        myperror("fork");
    1.92 -      close(p[0]);
    1.93 -      close(p[1]);
    1.94 +      close(cd->sock);
    1.95        free(cd);
    1.96        break;
    1.97      default:
    1.98        /* parent */
    1.99 -      trackChild(child, p[1]);
   1.100        processCount++;
   1.101 -      close(p[0]);
   1.102 +      close(cd->sock);
   1.103        free(cd);
   1.104        break;
   1.105      case 0:
   1.106 @@ -303,11 +241,11 @@
   1.107        /* Close all extraneous FDs */
   1.108        fd_max = getdtablesize();
   1.109        for (fd = STDERR_FILENO + 1; fd < fd_max; fd++) {
   1.110 -	if (fd != cd->sock && fd != p[0])
   1.111 +	if (fd != cd->sock && fd != pipefds[0])
   1.112  	  close(fd);
   1.113        }
   1.114  
   1.115 -      procClientHandler(cd, p[0]);
   1.116 +      procClientHandler(cd, pipefds[0]);
   1.117        exit(0);
   1.118      }
   1.119    }
   1.120 @@ -412,6 +350,7 @@
   1.121  static void
   1.122  procDie(int sig)
   1.123  {
   1.124 +  /* In case we're backgrounded */
   1.125    if (getpid() != _masterProcess) {
   1.126      kill(_masterProcess, sig);
   1.127      exit(0);
   1.128 @@ -426,6 +365,7 @@
   1.129  static void
   1.130  procReload(int sig)
   1.131  {
   1.132 +  /* In case we're backgrounded */
   1.133    if (getpid() != _masterProcess) {
   1.134      kill(_masterProcess, sig);
   1.135      exit(0);
   1.136 @@ -599,6 +539,12 @@
   1.137      handoff = threadHandoff;
   1.138    }
   1.139    else {
   1.140 +    /* Set up pipe for parent death detection */
   1.141 +    if (pipe(pipefds) == -1) {
   1.142 +      myperror("pipe");
   1.143 +      exit(2);
   1.144 +    }
   1.145 +
   1.146      _masterProcess = getpid();
   1.147      signal(SIGHUP, procReload);
   1.148      signal(SIGINT, procDie);
   1.149 @@ -607,10 +553,6 @@
   1.150    }
   1.151    multiprocess = forking; /* for wsgi.multithread & wsgi.multiprocess */
   1.152  
   1.153 -  /* Initialize list of children */
   1.154 -  childPipeHead.next = &childPipeTail;
   1.155 -  childPipeTail.prev = &childPipeHead;
   1.156 -
   1.157    /* Main loop */
   1.158    for(;;) {
   1.159      fd_set readfds;
   1.160 @@ -633,10 +575,7 @@
   1.161  
   1.162      /* Reap children, if any */
   1.163      if (forking) {
   1.164 -      pid_t child;
   1.165 -
   1.166 -      while ((child = waitpid(-1, &status, WNOHANG) > 0)) {
   1.167 -	forgetChild(child);
   1.168 +      while (waitpid(-1, &status, WNOHANG) > 0) {
   1.169  	if (processCount > 0) {
   1.170  	  processCount--;
   1.171  	}