You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ma...@hyperreal.org on 1999/05/24 04:10:28 UTC
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 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.