marc 97/02/19 19:20:19
Modified: src http_main.c Log: Add code to detect when a child process did not exit properly after a HUP and give it a prod. We do everything we can to make it die, since if it doesn't chances are the server won't be able to bind to the port on restart. For some reason, some children were not exiting and holding the whole show until they finish processing their MaxRequestsPerChild and exit. Reviewed by: Randy Terbush, Roy Fielding, Dean Gaudet Revision Changes Path 1.124 +51 -2 apache/src/http_main.c Index: http_main.c =================================================================== RCS file: /export/home/cvs/apache/src/http_main.c,v retrieving revision 1.123 retrieving revision 1.124 diff -C3 -r1.123 -r1.124 *** http_main.c 1997/02/18 08:06:14 1.123 --- http_main.c 1997/02/20 03:20:18 1.124 *************** *** 1030,1037 **** for (i = 0; i < HARD_SERVER_LIMIT; ++i) { int pid = scoreboard_image->servers[i].pid; ! if (pid != my_pid && pid != 0) ! waitpid (scoreboard_image->servers[i].pid, &status, 0); } } --- 1030,1086 ---- for (i = 0; i < HARD_SERVER_LIMIT; ++i) { int pid = scoreboard_image->servers[i].pid; ! if (pid != my_pid && pid != 0) { ! int waitret = 0, ! tries = 1; ! ! while (waitret == 0 && tries <= 4) { ! long int waittime = 4096; /* in usecs */ ! struct timeval tv; ! ! /* don't want to hold up progress any more than ! * necessary, so keep checking to see if the child ! * has exited with an exponential backoff. ! * Currently set for a maximum wait of a bit over ! * four seconds. ! */ ! while (((waitret = waitpid(pid, &status, WNOHANG)) == 0) && ! waittime < 3000000) { ! tv.tv_sec = waittime / 1000000; ! tv.tv_usec = waittime % 1000000; ! waittime = waittime * 2; ! select(0, NULL, NULL, NULL, &tv); ! } ! if (waitret == 0) { ! switch (tries) { ! case 1: ! /* perhaps it missed the SIGHUP, lets try again */ ! log_printf(server_conf, "child process %d did not exit, sending another SIGHUP", pid); ! kill(pid, SIGHUP); ! break; ! case 2: ! /* ok, now it's being annoying */ ! log_printf(server_conf, "child process %d still did not exit, sending a SIGTERM", pid); ! kill(pid, SIGTERM); ! break; ! case 3: ! /* die child scum */ ! log_printf(server_conf, "child process %d still did not exit, sending a SIGKILL", pid); ! kill(pid, SIGKILL); ! break; ! case 4: ! /* gave it our best shot, but alas... If this really ! * is a child we are trying to kill and it really hasn't ! * exited, we will likely fail to bind to the port ! * after the restart. ! */ ! log_printf(server_conf, "could not make child process %d exit, attempting to continue anyway", pid); ! break; ! } ! } ! tries++; ! } ! } } }