Return-Path: Delivered-To: apache-cvs-archive@hyperreal.org Received: (qmail 1983 invoked by uid 6000); 24 May 1999 02:10:30 -0000 Received: (qmail 1977 invoked by alias); 24 May 1999 02:10:29 -0000 Delivered-To: apache-apr-cvs@hyperreal.org Received: (qmail 1975 invoked by uid 216); 24 May 1999 02:10:28 -0000 Date: 24 May 1999 02:10:28 -0000 Message-ID: <19990524021028.1974.qmail@hyperreal.org> From: manoj@hyperreal.org To: apache-apr-cvs@hyperreal.org Subject: cvs commit: apache-apr/pthreads/src/main http_accept.c http_main.c Sender: apache-cvs-owner@apache.org Precedence: bulk Reply-To: new-httpd@apache.org manoj 99/05/23 19:10:28 Modified: pthreads/src/include http_main.h pthreads/src/main http_accept.c http_main.c Log: Switch to using a pipe to notify children of graceful shutodwn instead of a signal. This also naturally solves a problem with graceful shutdown of children blocked on the accept mutex. Revision Changes Path 1.6 +3 -0 apache-apr/pthreads/src/include/http_main.h Index: http_main.h =================================================================== RCS file: /home/cvs/apache-apr/pthreads/src/include/http_main.h,v retrieving revision 1.5 retrieving revision 1.6 diff -u -u -r1.5 -r1.6 --- http_main.h 1999/04/09 04:10:35 1.5 +++ http_main.h 1999/05/24 02:10:25 1.6 @@ -58,6 +58,9 @@ #ifndef APACHE_HTTP_MAIN_H #define APACHE_HTTP_MAIN_H +/* Pipe used to signal a graceful child shutdown */ +extern int ap_pipe_of_death[2]; + #ifdef __cplusplus extern "C" { #endif 1.15 +19 -15 apache-apr/pthreads/src/main/http_accept.c Index: http_accept.c =================================================================== RCS file: /home/cvs/apache-apr/pthreads/src/main/http_accept.c,v retrieving revision 1.14 retrieving revision 1.15 diff -u -u -r1.14 -r1.15 --- http_accept.c 1999/05/20 05:00:41 1.14 +++ http_accept.c 1999/05/24 02:10:26 1.15 @@ -331,7 +331,6 @@ */ static listen_rec *head_listener; static struct pollfd *listenfds; -static int pipe_of_death; void accept_parent_init(pool *pconf, int listener_count) { @@ -344,7 +343,6 @@ int worker_threads_per_child) { int i; - int pipe_pair_of_death[2]; listen_rec *lr; SAFE_ACCEPT(intra_mutex_init(pchild, 1)); @@ -353,15 +351,7 @@ head_listener = ap_listeners; listenfds = ap_palloc(pchild, sizeof(struct pollfd) * (num_listenfds + 1)); - - if (pipe(pipe_pair_of_death) == -1) { - ap_log_error(APLOG_MARK, APLOG_ERR, - (const server_rec*) ap_get_server_conf(), - "pipe: (pipe_of_death)"); - clean_child_exit(1); - } - pipe_of_death = pipe_pair_of_death[1]; - listenfds[0].fd = pipe_pair_of_death[0]; + listenfds[0].fd = ap_pipe_of_death[0]; listenfds[0].events = POLLIN; listenfds[0].revents = 0; for (lr = ap_listeners, i = 1; i <= num_listenfds; lr = lr->next, ++i) { @@ -380,7 +370,9 @@ int csd = -1; int sd; int srv; + int ret; listen_rec *lr; + char pipe_read_char; size_t len = sizeof(struct sockaddr); @@ -400,6 +392,21 @@ break; srv = poll(listenfds, num_listenfds + 1, -1); + if (listenfds[0].revents & POLLIN) { + /* A process has gotten a signal on the shutdown pipe. + * Check if we're the lucky process to die. */ + ret = read(listenfds[0].fd, &pipe_read_char, 1); + if (ret == -1 && errno == EAGAIN) { + /* It lost the lottery. It must continue to suffer through + * a life of servitude */ + continue; + } + else { + /* It won the lottery (or something else is very wrong). + * Embrace death with open arms. */ + break; + } + } if (workers_may_exit) break; if (srv < 0) { @@ -472,6 +479,7 @@ break; } } + workers_may_exit = 1; return -1; } @@ -479,15 +487,11 @@ { int i; int index = find_child_by_pid(getpid()); - char char_of_death = '!'; parent_score *ss = &ap_scoreboard_image->parent[index]; requests_this_child = 0; workers_may_exit = 1; - - /* Kick threads out of poll */ - (void) write(pipe_of_death, &char_of_death, 1); for (i = 0; i < ss->worker_threads; i++) { pthread_join(ap_scoreboard_image->servers[index][i].tid, NULL); 1.81 +26 -9 apache-apr/pthreads/src/main/http_main.c Index: http_main.c =================================================================== RCS file: /home/cvs/apache-apr/pthreads/src/main/http_main.c,v retrieving revision 1.80 retrieving revision 1.81 diff -u -u -r1.80 -r1.81 --- http_main.c 1999/05/20 04:33:32 1.80 +++ http_main.c 1999/05/24 02:10:27 1.81 @@ -216,6 +216,7 @@ array_header *ap_server_config_defines; pool *pchild; /* Pool for httpd child stuff */ +int ap_pipe_of_death[2]; /* thread local storage code that isn't used right now */ @@ -1963,7 +1964,6 @@ /* XXX - Do the appropriate thing for each signal */ switch (signal_received) { case SIGWINCH: - graceful_sig_handler(SIGWINCH); for (j = 0; j < ap_threads_per_child + ap_acceptors_per_child; j++) { /* Useful for debugging */ @@ -2158,11 +2158,11 @@ } max_daemons_limit = last_non_dead + 1; if (idle_count > ap_daemons_max_free) { - /* kill off one child... we use SIGWINCH because that'll cause it to - * shut down gracefully, in case it happened to pick up a request - * while we were counting - */ - kill(ap_scoreboard_image->parent[to_kill].pid, SIGWINCH); + /* Kill off one child */ + char char_of_death = '!'; + if (write(ap_pipe_of_death[1], &char_of_death, 1) == -1) { + ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "write ap_pipe_of_death"); + } idle_spawn_rate = 1; } else if (idle_count < ap_daemons_min_free) { @@ -2288,6 +2288,20 @@ ap_restart_time = time(NULL); /* ZZZZZ */ } ap_clear_pool(pconf); + if (pipe(ap_pipe_of_death) == -1) { + ap_log_error(APLOG_MARK, APLOG_ERR, + (const server_rec*) ap_get_server_conf(), + "pipe: (pipe_of_death)"); + exit(1); + } + ap_note_cleanups_for_fd(pconf, ap_pipe_of_death[0]); + ap_note_cleanups_for_fd(pconf, ap_pipe_of_death[1]); + if (fcntl(ap_pipe_of_death[0], F_SETFD, O_NONBLOCK) == -1) { + ap_log_error(APLOG_MARK, APLOG_ERR, + (const server_rec*) ap_get_server_conf(), + "fcntl: O_NONBLOCKing (pipe_of_death)"); + exit(1); + } ptemp = ap_make_sub_pool(pconf); server_conf = ap_read_config(pconf, ptemp, ap_server_confname); listener_count = setup_listeners(pconf); @@ -2385,14 +2399,17 @@ if (is_graceful) { int i, j; + char char_of_death = '!'; ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf, "SIGWINCH received. Doing graceful restart"); /* kill off the idle ones */ - if (ap_killpg(pgrp, SIGWINCH) < 0) { - ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "killpg SIGWINCH"); - } + for (i = 0; i < ap_daemons_limit; ++i) { + if (write(ap_pipe_of_death[1], &char_of_death, 1) == -1) { + ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "write ap_pipe_of_death"); + } + } /* This is mostly for debugging... so that we know what is still * gracefully dealing with existing request.