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 }
