cvs commit: apache-apr/pthreads/src/main http_accept.c http_main.c
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 ChangesPath 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 -15apache-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
cvs commit: apache-apr/pthreads/src/main http_accept.c http_main.c
manoj 99/04/29 12:34:23 Modified:.STATUS pthreads/src/main http_accept.c http_main.c Log: Get rid of thread_starter_thread, and just start all of our worker threads from child_main. This makes the code simpler, and eliminates any race conditions involving trying to shutdown a child process while still starting threads. Revision ChangesPath 1.23 +1 -9 apache-apr/STATUS Index: STATUS === RCS file: /home/cvs/apache-apr/STATUS,v retrieving revision 1.22 retrieving revision 1.23 diff -u -u -r1.22 -r1.23 --- STATUS1999/04/27 06:23:04 1.22 +++ STATUS1999/04/29 19:34:19 1.23 @@ -1,5 +1,5 @@ Apache Portable Runtime STATUS: -Last modified at [$Date: 1999/04/27 06:23:04 $] +Last modified at [$Date: 1999/04/29 19:34:19 $] Release: @@ -42,14 +42,6 @@ Everything Needs patch: - -On Red Hat 5.2, with a very low MaxRequestsPerChild (e.g. 10), when the -server is banged on with ApacheBench, occasionally, the main thread of a -process hangs around in pthread_exit_process. The size of that process is -always around 11M. This bug is also exhibited by sending lots of SIGHUPs -to the parent process rapidly (but not SIGWINCHes). The suspicion is that -this is either an error in how pthread calls are used in the server, or a -libc bug (the last refuge of a desperate programer). When the server runs at a high load, and the load later drops off, the server tries to kill off some children. The problem is that the 1.11 +1 -12 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.10 retrieving revision 1.11 diff -u -u -r1.10 -r1.11 --- http_accept.c 1999/04/22 05:46:53 1.10 +++ http_accept.c 1999/04/29 19:34:20 1.11 @@ -245,7 +245,7 @@ */ int i = ap_threads_per_child; if (lr) { -while (lr->next != NULL) { +while (lr != NULL) { (void) ap_update_child_status(my_child_num, i, SERVER_STARTING, (request_rec *) NULL); @@ -277,17 +277,6 @@ /* no listening sockets Kill the server please. */ exit(0); } -(void) ap_update_child_status(my_child_num, i, SERVER_STARTING, - (request_rec *) NULL); - -my_info = NULL; - -my_info = (proc_info *) malloc(sizeof(proc_info)); -my_info->pid = my_child_num; -my_info->tid = i; -my_info->sd = lr->fd; - -accept_thread(my_info); } int get_connection(struct sockaddr *sa_client) 1.78 +31 -52apache-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.77 retrieving revision 1.78 diff -u -u -r1.77 -r1.78 --- http_main.c 1999/04/22 04:14:40 1.77 +++ http_main.c 1999/04/29 19:34:21 1.78 @@ -1884,61 +1884,16 @@ #endif /* ndef WIN32 */ } -static void *thread_starter_thread(void *thread_arg) { -int i; -pthread_t thread; -int my_child_num = *((int *) thread_arg); -proc_info *my_info = NULL; - -/* Setup worker threads */ -for (i=0; i < ap_threads_per_child; i++) { - -my_info = NULL; - - my_info = (proc_info *)malloc(sizeof(proc_info)); - my_info->pid = my_child_num; -my_info->tid = i; - my_info->sd = 0; - - /* We are creating threads right now */ - (void) ap_update_child_status(my_child_num, i, SERVER_STARTING, - (request_rec *) NULL); - if (pthread_create(&thread, NULL, worker_thread, my_info)) { - ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf, - "pthread_create: unable to create worker thread"); - /* - * We failed to create a thread. Update the scoreboard, - * or it will say SERVER_STARTING forever. - */ - (void) ap_update_child_status(my_child_num, i, SERVER_DEAD, - (request_rec *) NULL); - exit(1); /* We won't always exit here, but for no this is okay */ - } - - /* We let each thread update it's own scoreboard entry. This is done - * because it let's us deal with tid better. - */ -} - - -/* Begin accepting requests - * Design: - * - */ -start_accepting_connections(my_child_num); -return NULL; -} - static void child_main(int c
cvs commit: apache-apr/pthreads/src/main http_accept.c http_main.c
manoj 99/04/16 21:25:57 Modified:pthreads/src/include http_accept.h pthreads/src/main http_accept.c http_main.c Log: An attempt to put SINGLE_LISTEN_UNSERIALIZED_ACCEPT support back in. This also moves the SAFE_ACCEPT definition from http_accept.h to http_accept.c since it isn't (and shouldn't be) used in other files anymore. Revision ChangesPath 1.6 +0 -2 apache-apr/pthreads/src/include/http_accept.h Index: http_accept.h === RCS file: /home/cvs/apache-apr/pthreads/src/include/http_accept.h,v retrieving revision 1.5 retrieving revision 1.6 diff -u -u -r1.5 -r1.6 --- http_accept.h 1999/04/17 03:35:53 1.5 +++ http_accept.h 1999/04/17 04:25:55 1.6 @@ -65,8 +65,6 @@ #include "httpd.h" #include "ap_config.h" -#define SAFE_ACCEPT(stmt) do {stmt;} while(0) - /* The info each server thread needs to start correctly. */ typedef struct { 1.9 +16 -0 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.8 retrieving revision 1.9 diff -u -u -r1.8 -r1.9 --- http_accept.c 1999/04/17 01:58:58 1.8 +++ http_accept.c 1999/04/17 04:25:56 1.9 @@ -72,6 +72,15 @@ static int num_listenfds; #if defined (USE_ACCEPT_QUEUE) + +#ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT +/* Each thread only listens to one socket in this model, so the starvation + * problem described in manual/misc/perf-tuning.html can't occur here */ +#define SAFE_ACCEPT(stmt) +#else +#define SAFE_ACCEPT(stmt) do {stmt;} while(0) +#endif + /* The queue of sockets we've accepted */ static FDQueue csd_queue; @@ -311,6 +320,13 @@ } #elif defined(USE_MULTI_ACCEPT) + +#ifdef SINGLE_LISTEN_UNSERIALIZED_ACCEPT +#define SAFE_ACCEPT(stmt) do {if(ap_listeners->next != NULL) {stmt;}} while(0) +#else +#define SAFE_ACCEPT(stmt) do {stmt;} while(0) +#endif + /* * USE_MULTI_ACCEPT * Worker threads do the accept and process the request. 1.73 +0 -7 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.72 retrieving revision 1.73 diff -u -u -r1.72 -r1.73 --- http_main.c 1999/04/15 20:01:40 1.72 +++ http_main.c 1999/04/17 04:25:56 1.73 @@ -416,13 +416,6 @@ } } -/* On some architectures it's safe to do unserialized accept()s in the single - * Listen case. But it's never safe to do it in the case where there's - * multiple Listen statements. Define SINGLE_LISTEN_UNSERIALIZED_ACCEPT - * when it's safe in the single Listen case. We haven't defined this yet - * for the hybrid server. ZZZ - */ - static void usage(char *bin) { char pad[MAX_STRING_LEN];
cvs commit: apache-apr/pthreads/src/main http_accept.c http_main.c
manoj 99/04/14 14:38:30 Modified:pthreads/src/include http_accept.h pthreads/src/main http_accept.c http_main.c Log: Some tweaking of our http_accept modularization. A call is added to perform any initialization needed in the parent. With this, we can take all knowledge about accept serialization out of http_main.c. Also, the function names were changed as a result of this addition and to keep the difference between "request" and "connection" straight. accept_parent_init (NEW) init_accept -> accept_child_init start_accepting_requests -> start_accepting_connections get_request -> get_connection stop_accepting_requests -> stop_accepting_connections Revision ChangesPath 1.3 +5 -13 apache-apr/pthreads/src/include/http_accept.h Index: http_accept.h === RCS file: /home/cvs/apache-apr/pthreads/src/include/http_accept.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -u -r1.2 -r1.3 --- http_accept.h 1999/04/14 21:03:18 1.2 +++ http_accept.h 1999/04/14 21:38:28 1.3 @@ -79,19 +79,11 @@ #define USE_ACCEPT_QUEUE /*#define USE_MULTI_ACCEPT*/ -#if defined (USE_ACCEPT_QUEUE) -void init_accept(pool*, int, int); -void start_accepting_requests(int); -int get_request(struct sockaddr *); -void stop_accepting_requests(pool*); - -#elif defined (USE_MULTI_ACCEPT) -void init_accept(pool*,int, int); -void start_accepting_requests(int); -int get_request(struct sockaddr *); -void stop_accepting_requests(pool *); -#endif - +void accept_parent_init(pool*); +void accept_child_init(pool*, int, int); +void start_accepting_connections(int); +int get_connection(struct sockaddr *); +void stop_accepting_connections(pool*); #ifdef __cplusplus } 1.5 +17 -8 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.4 retrieving revision 1.5 diff -u -u -r1.4 -r1.5 --- http_accept.c 1999/04/14 21:03:26 1.4 +++ http_accept.c 1999/04/14 21:38:28 1.5 @@ -181,6 +181,11 @@ } } +void accept_parent_init(pool *pconf) +{ +SAFE_ACCEPT(accept_mutex_init(pconf)); +} + /* * Description: * Do any setup or initialization required before worker threads begin @@ -191,7 +196,7 @@ * 3. Pass in server_conf? * 4. Simply access the globals (yech...) */ -void init_accept(pool* pchild, +void accept_child_init(pool* pchild, int worker_threads_per_child, int acceptor_threads_per_child) { @@ -202,7 +207,7 @@ } -void start_accepting_requests(int my_child_num) +void start_accepting_connections(int my_child_num) { proc_info *my_info; pthread_t thread; @@ -275,7 +280,7 @@ accept_thread(my_info); } -int get_request(struct sockaddr *sa_client) +int get_connection(struct sockaddr *sa_client) { int csd = -1; int block_if_empty = 1; @@ -295,7 +300,7 @@ return csd; } -void stop_accepting_requests(pool* pconf) +void stop_accepting_connections(pool* pconf) { requests_this_child = 0; /* The two functions to get all of our other threads to die off. */ @@ -313,8 +318,12 @@ static int num_listenfds; static struct pollfd *listenfds; +void accept_parent_init(pool *pconf) +{ +SAFE_ACCEPT(accept_mutex_init(pconf)); +} -void init_accept(pool* pchild, +void accept_child_init(pool* pchild, int worker_threads_per_child, int acceptors_per_child) { @@ -336,10 +345,10 @@ } } -void start_accepting_requests(int my_child_num) +void start_accepting_connections(int my_child_num) { } -int get_request(struct sockaddr *sa_client) +int get_connection(struct sockaddr *sa_client) { int csd = -1; int sd; @@ -446,7 +455,7 @@ return -1; } -void stop_accepting_requests(pool* pconf) +void stop_accepting_connections(pool* pconf) { listen_rec *lr; 1.70 +5 -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.69 retrieving revision 1.70 diff -u -u -r1.69 -r1.70 --- http_main.c 1999/04/14 21:03:29 1.69 +++ http_main.c 1999/04/14 21:38:29 1.70 @@ -92,9 +92,6 @@ #include "util_script.h" /* to force util_script.c linking */ #include "util_uri.h" #include "scoreboard.h" -/* XXX - the accept_mutex_init call should be moved to http_accept.c. Until - * that...