You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Rodent of Unusual Size <co...@decus.org> on 1997/08/19 19:26:51 UTC
SIG{TERM,KILL} and child_exit
>From the fingers of Dean Gaudet flowed the following:
>
> The main one I have is buffered (but
>still atomic) logging. It would be an option of course. It actually uses
>child_exit, whee!
Erm, how is it doing that? Alexei already identified that
child_exit shouldn't be working cleanly on normal server shutdown:
void sig_term(int sig) {
log_error("httpd: caught SIGTERM, shutting down", server_conf);
cleanup_scoreboard();
accept_mutex_cleanup();
#ifdef SIGKILL
ap_killpg (pgrp, SIGKILL);
#endif /* SIGKILL */
close(sd);
exit(1);
}
It looks like child_exit will actually only get called on
child_oldage. I've been meaning to look at a solution for this, but
I'm pretty far behind. I agree with Alexei that this needs to be
addressed before 1.3b1.
#ken :-)}
Re: [PATCH] Re: SIG{TERM,KILL} and child_exit
Posted by Dean Gaudet <dg...@arctic.org>.
On Tue, 19 Aug 1997, Dean Gaudet wrote:
> I'd move destroy_pool into child_exit_modules, just for consistency.
Ok how about creating a child_exit() routine. I really don't want all
that duplicated code all over the place ...
Dean
Re: [PATCH] Re: SIG{TERM,KILL} and child_exit
Posted by Alexei Kosut <ak...@organic.com>.
On Tue, 19 Aug 1997, Dean Gaudet wrote:
> This looks like a good start.
>
> I'd move destroy_pool into child_exit_modules, just for consistency.
No; child_exit_modules() shouldn't, IMHO, do anything more than call the
child_exit API handlers. None of the other http_config functions do
anything but that. Adding other functionality, like destroying pools or
exiting, is asking for trouble, because you might want to use
call_exit_modules() for some other purpose (I have no idea what). That's
why I moved (in my patch) exit() out of child_exit_modules.
> accept_mutex_cleanup() and cleanup_scoreboard() absolutely must be called.
> You seem to have lost them below.
Erg. You're right. I forgot about that.
-- Alexei Kosut <ak...@organic.com>
Re: [PATCH] Re: SIG{TERM,KILL} and child_exit
Posted by Dean Gaudet <dg...@arctic.org>.
This looks like a good start.
I'd move destroy_pool into child_exit_modules, just for consistency.
accept_mutex_cleanup() and cleanup_scoreboard() absolutely must be called.
You seem to have lost them below.
If you receive a SIGTERM during a reclaim_child_processes it will abort
the select() ... probably not a big problem though. Just messes up timing
a wee bit.
Dean
On Tue, 19 Aug 1997, Alexei Kosut wrote:
> On Tue, 19 Aug 1997, Rodent of Unusual Size wrote:
>
> > It looks like child_exit will actually only get called on
> > child_oldage. I've been meaning to look at a solution for this, but
>
> And SIGHUP.
>
> > I'm pretty far behind. I agree with Alexei that this needs to be
> > addressed before 1.3b1.
>
> Yes. Here's a patch (not fully tested) that I think fixes the SIGTERM
> issues, as well as fixing a part of the child_exit() stuff (it wasn't
> calling destroy_pool, which it should). There's still some win32 stuff
> that needs to be done (I don't think it calls child_exit at all the
> correct times, and I'm relatively sure it doesn't call child_init), but
> this should work for Unix:
>
> Index: core/http_config.c
> ===================================================================
> RCS file: /export/home/cvs/apachen/src/core/http_config.c,v
> retrieving revision 1.73
> diff -u -r1.73 http_config.c
> --- http_config.c 1997/08/18 07:17:24 1.73
> +++ http_config.c 1997/08/19 19:19:28
> @@ -1270,7 +1270,6 @@
> if (m->child_exit)
> (*m->child_exit) (s, p);
>
> - exit(0);
> }
>
> /********************************************************************
> Index: core/http_main.c
> ===================================================================
> RCS file: /export/home/cvs/apachen/src/core/http_main.c,v
> retrieving revision 1.204
> diff -u -r1.204 http_main.c
> --- http_main.c 1997/08/18 07:17:25 1.204
> +++ http_main.c 1997/08/19 19:19:33
> @@ -746,6 +746,8 @@
> if (alarms_blocked == 0) {
> if (exit_after_unblock) {
> child_exit_modules(pconf, server_conf);
> + destroy_pool(pconf);
> + exit(0);
> }
> if (alarm_pending) {
> alarm_pending = 0;
> @@ -1591,7 +1593,7 @@
> return -1;
> }
>
> -static void reclaim_child_processes (void)
> +static void reclaim_child_processes (int start_tries)
> {
> #ifndef MULTITHREAD
> int i, status;
> @@ -1602,7 +1604,7 @@
>
> if (pid != my_pid && pid != 0) {
> int waitret = 0,
> - tries = 1;
> + tries = start_tries;
>
> while (waitret == 0 && tries <= 4) {
> long int waittime = 4096; /* in usecs */
> @@ -1745,17 +1747,6 @@
> }
>
>
> -void sig_term(int sig) {
> - log_error("httpd: caught SIGTERM, shutting down", server_conf);
> - cleanup_scoreboard();
> - accept_mutex_cleanup();
> -#ifdef SIGKILL
> - ap_killpg (pgrp, SIGKILL);
> -#endif /* SIGKILL */
> - close(sd);
> - exit(1);
> -}
> -
> void bus_error(int sig) {
> char emsg[256];
>
> @@ -1790,6 +1781,8 @@
> exit_after_unblock = 1;
> } else {
> child_exit_modules(pconf, server_conf);
> + destroy_pool(pconf);
> + exit(0);
> }
> }
>
> @@ -1805,10 +1798,15 @@
> }
>
> /* volatile just in case */
> +static int volatile shutdown_pending;
> static int volatile restart_pending;
> static int volatile is_graceful;
> static int volatile generation;
>
> +static void sig_term(int sig) {
> + shutdown_pending = 1;
> +}
> +
> static void restart (int sig)
> {
> #ifdef WIN32
> @@ -2642,13 +2640,18 @@
> clear_pool (ptrans);
>
> sync_scoreboard_image();
> - if (scoreboard_image->global.exit_generation >= generation)
> + if (scoreboard_image->global.exit_generation >= generation) {
> child_exit_modules(pconf, server_conf);
> + destroy_pool(pconf);
> + exit(0);
> + }
>
> if ((max_requests_per_child > 0
> && ++requests_this_child >= max_requests_per_child))
> {
> child_exit_modules(pconf, server_conf);
> + destroy_pool(pconf);
> + exit(0);
> }
>
> (void)update_child_status(my_child_num, SERVER_READY, (request_rec*)NULL);
> @@ -2692,6 +2695,8 @@
> if (deferred_die) {
> /* we didn't get a socket, and we were told to die */
> child_exit_modules(pconf, server_conf);
> + destroy_pool(pconf);
> + exit(0);
> }
> }
>
> @@ -2714,13 +2719,18 @@
> if (deferred_die) {
> /* ok maybe not, see ya later */
> child_exit_modules(pconf, server_conf);
> + destroy_pool(pconf);
> + exit(0);
> }
> /* or maybe we missed a signal, you never know on systems
> * without reliable signals
> */
> sync_scoreboard_image();
> - if (scoreboard_image->global.exit_generation >= generation)
> + if (scoreboard_image->global.exit_generation >= generation) {
> child_exit_modules(pconf, server_conf);
> + destroy_pool(pconf);
> + exit(0);
> + }
> }
>
> SAFE_ACCEPT(accept_mutex_off()); /* unlock after "accept" */
> @@ -2805,6 +2815,8 @@
> if (scoreboard_image->global.exit_generation >= generation) {
> bclose(conn_io);
> child_exit_modules(pconf, server_conf);
> + destroy_pool(pconf);
> + exit(0);
> }
>
> /* In case we get a graceful restart while we're blocked
> @@ -3126,9 +3138,9 @@
>
> log_error ("Server configured -- resuming normal operations",
> server_conf);
> - restart_pending = 0;
> + restart_pending = shutdown_pending = 0;
>
> - while (!restart_pending) {
> + while (!restart_pending && !shutdown_pending) {
> int child_slot;
> int pid = wait_or_timeout ();
>
> @@ -3179,6 +3191,21 @@
> perform_idle_server_maintenance();
> }
>
> + if (shutdown_pending) {
> + /* Time to gracefully shut down:
> + * Kill child processes, tell them to call child_exit, etc...
> + */
> + if (ap_killpg (pgrp, SIGTERM) < 0) {
> + log_unixerr ("killpg SIGTERM", NULL, NULL, server_conf);
> + }
> + reclaim_child_processes(2); /* Start with SIGTERM */
> + log_error("httpd: caught SIGTERM, shutting down", server_conf);
> +
> + /* Clear the pool - including any registered cleanups */
> + destroy_pool(pconf);
> + exit(0);
> + }
> +
> /* we've been told to restart */
> signal (SIGHUP, SIG_IGN);
> signal (SIGUSR1, SIG_IGN);
> @@ -3222,7 +3249,7 @@
> if (ap_killpg (pgrp, SIGHUP) < 0) {
> log_unixerr ("killpg SIGHUP", NULL, NULL, server_conf);
> }
> - reclaim_child_processes(); /* Not when just starting up */
> + reclaim_child_processes(1); /* Not when just starting up */
> log_error ("SIGHUP received. Attempting to restart", server_conf);
> }
> ++generation;
>
>
> -- Alexei Kosut <ak...@organic.com>
>
>
[PATCH] Re: SIG{TERM,KILL} and child_exit
Posted by Alexei Kosut <ak...@organic.com>.
On Tue, 19 Aug 1997, Rodent of Unusual Size wrote:
> It looks like child_exit will actually only get called on
> child_oldage. I've been meaning to look at a solution for this, but
And SIGHUP.
> I'm pretty far behind. I agree with Alexei that this needs to be
> addressed before 1.3b1.
Yes. Here's a patch (not fully tested) that I think fixes the SIGTERM
issues, as well as fixing a part of the child_exit() stuff (it wasn't
calling destroy_pool, which it should). There's still some win32 stuff
that needs to be done (I don't think it calls child_exit at all the
correct times, and I'm relatively sure it doesn't call child_init), but
this should work for Unix:
Index: core/http_config.c
===================================================================
RCS file: /export/home/cvs/apachen/src/core/http_config.c,v
retrieving revision 1.73
diff -u -r1.73 http_config.c
--- http_config.c 1997/08/18 07:17:24 1.73
+++ http_config.c 1997/08/19 19:19:28
@@ -1270,7 +1270,6 @@
if (m->child_exit)
(*m->child_exit) (s, p);
- exit(0);
}
/********************************************************************
Index: core/http_main.c
===================================================================
RCS file: /export/home/cvs/apachen/src/core/http_main.c,v
retrieving revision 1.204
diff -u -r1.204 http_main.c
--- http_main.c 1997/08/18 07:17:25 1.204
+++ http_main.c 1997/08/19 19:19:33
@@ -746,6 +746,8 @@
if (alarms_blocked == 0) {
if (exit_after_unblock) {
child_exit_modules(pconf, server_conf);
+ destroy_pool(pconf);
+ exit(0);
}
if (alarm_pending) {
alarm_pending = 0;
@@ -1591,7 +1593,7 @@
return -1;
}
-static void reclaim_child_processes (void)
+static void reclaim_child_processes (int start_tries)
{
#ifndef MULTITHREAD
int i, status;
@@ -1602,7 +1604,7 @@
if (pid != my_pid && pid != 0) {
int waitret = 0,
- tries = 1;
+ tries = start_tries;
while (waitret == 0 && tries <= 4) {
long int waittime = 4096; /* in usecs */
@@ -1745,17 +1747,6 @@
}
-void sig_term(int sig) {
- log_error("httpd: caught SIGTERM, shutting down", server_conf);
- cleanup_scoreboard();
- accept_mutex_cleanup();
-#ifdef SIGKILL
- ap_killpg (pgrp, SIGKILL);
-#endif /* SIGKILL */
- close(sd);
- exit(1);
-}
-
void bus_error(int sig) {
char emsg[256];
@@ -1790,6 +1781,8 @@
exit_after_unblock = 1;
} else {
child_exit_modules(pconf, server_conf);
+ destroy_pool(pconf);
+ exit(0);
}
}
@@ -1805,10 +1798,15 @@
}
/* volatile just in case */
+static int volatile shutdown_pending;
static int volatile restart_pending;
static int volatile is_graceful;
static int volatile generation;
+static void sig_term(int sig) {
+ shutdown_pending = 1;
+}
+
static void restart (int sig)
{
#ifdef WIN32
@@ -2642,13 +2640,18 @@
clear_pool (ptrans);
sync_scoreboard_image();
- if (scoreboard_image->global.exit_generation >= generation)
+ if (scoreboard_image->global.exit_generation >= generation) {
child_exit_modules(pconf, server_conf);
+ destroy_pool(pconf);
+ exit(0);
+ }
if ((max_requests_per_child > 0
&& ++requests_this_child >= max_requests_per_child))
{
child_exit_modules(pconf, server_conf);
+ destroy_pool(pconf);
+ exit(0);
}
(void)update_child_status(my_child_num, SERVER_READY, (request_rec*)NULL);
@@ -2692,6 +2695,8 @@
if (deferred_die) {
/* we didn't get a socket, and we were told to die */
child_exit_modules(pconf, server_conf);
+ destroy_pool(pconf);
+ exit(0);
}
}
@@ -2714,13 +2719,18 @@
if (deferred_die) {
/* ok maybe not, see ya later */
child_exit_modules(pconf, server_conf);
+ destroy_pool(pconf);
+ exit(0);
}
/* or maybe we missed a signal, you never know on systems
* without reliable signals
*/
sync_scoreboard_image();
- if (scoreboard_image->global.exit_generation >= generation)
+ if (scoreboard_image->global.exit_generation >= generation) {
child_exit_modules(pconf, server_conf);
+ destroy_pool(pconf);
+ exit(0);
+ }
}
SAFE_ACCEPT(accept_mutex_off()); /* unlock after "accept" */
@@ -2805,6 +2815,8 @@
if (scoreboard_image->global.exit_generation >= generation) {
bclose(conn_io);
child_exit_modules(pconf, server_conf);
+ destroy_pool(pconf);
+ exit(0);
}
/* In case we get a graceful restart while we're blocked
@@ -3126,9 +3138,9 @@
log_error ("Server configured -- resuming normal operations",
server_conf);
- restart_pending = 0;
+ restart_pending = shutdown_pending = 0;
- while (!restart_pending) {
+ while (!restart_pending && !shutdown_pending) {
int child_slot;
int pid = wait_or_timeout ();
@@ -3179,6 +3191,21 @@
perform_idle_server_maintenance();
}
+ if (shutdown_pending) {
+ /* Time to gracefully shut down:
+ * Kill child processes, tell them to call child_exit, etc...
+ */
+ if (ap_killpg (pgrp, SIGTERM) < 0) {
+ log_unixerr ("killpg SIGTERM", NULL, NULL, server_conf);
+ }
+ reclaim_child_processes(2); /* Start with SIGTERM */
+ log_error("httpd: caught SIGTERM, shutting down", server_conf);
+
+ /* Clear the pool - including any registered cleanups */
+ destroy_pool(pconf);
+ exit(0);
+ }
+
/* we've been told to restart */
signal (SIGHUP, SIG_IGN);
signal (SIGUSR1, SIG_IGN);
@@ -3222,7 +3249,7 @@
if (ap_killpg (pgrp, SIGHUP) < 0) {
log_unixerr ("killpg SIGHUP", NULL, NULL, server_conf);
}
- reclaim_child_processes(); /* Not when just starting up */
+ reclaim_child_processes(1); /* Not when just starting up */
log_error ("SIGHUP received. Attempting to restart", server_conf);
}
++generation;
-- Alexei Kosut <ak...@organic.com>
Re: SIG{TERM,KILL} and child_exit
Posted by Dean Gaudet <dg...@arctic.org>.
Oh yeah, so there's that bug to be fixed ;) sig_term could do a
reclaim_child_processes in which case it needs to have Nathan's bug fixed
... uh I forget the PR, but we just fixed it for SIGHUP and SIGUSR1. An
issue is that during a USR1/HUP restart I don't really care if another
restart signal is received, we'll just continue restarting. But if a
SIGTERM is received we want to stop restarting and do an exit and cleanup.
It's not a quick fix, but needs to happen for 1.3.
My new log buffer code keeps a 4k buffer. If a log entry would overflow
the buffer it flushes first, then starts off the fresh buffer with the new
entry. On child_exit it flushes the log. This maintains the atomicity
... but I really need to use whatever POSIX #define it is that defines the
max atomic write.
Dean
On Tue, 19 Aug 1997, Rodent of Unusual Size wrote:
> >From the fingers of Dean Gaudet flowed the following:
> >
> > The main one I have is buffered (but
> >still atomic) logging. It would be an option of course. It actually uses
> >child_exit, whee!
>
> Erm, how is it doing that? Alexei already identified that
> child_exit shouldn't be working cleanly on normal server shutdown:
>
> void sig_term(int sig) {
> log_error("httpd: caught SIGTERM, shutting down", server_conf);
> cleanup_scoreboard();
> accept_mutex_cleanup();
> #ifdef SIGKILL
> ap_killpg (pgrp, SIGKILL);
> #endif /* SIGKILL */
> close(sd);
> exit(1);
> }
>
> It looks like child_exit will actually only get called on
> child_oldage. I've been meaning to look at a solution for this, but
> I'm pretty far behind. I agree with Alexei that this needs to be
> addressed before 1.3b1.
>
> #ken :-)}
>