You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Ben Laurie <be...@gonzo.ben.algroup.co.uk> on 1996/06/23 14:02:24 UTC
"Graceful Restart" patch
Guys,
I've worked up this patch to enable a graceful restart of Apache. Essentially
the idea is this: you send the main process a SIGINT (kill -2) and it invites
the children to die politely. It then waits until they all have (which they do
at the end of the _next_ request). Then it restarts as if it had a SIGHUP. I'm
not particularly proposing that this should go into 1.1, though it ought to be
pretty harmless unless actually used, but I'd appreciate it if people could
give it a try and let me know what they think.
Cheers,
Ben.
Index: http_main.c
===================================================================
RCS file: /export/home/cvs/apache/src/http_main.c,v
retrieving revision 1.40
diff -c -r1.40 http_main.c
*** http_main.c 1996/06/22 13:58:34 1.40
--- http_main.c 1996/06/23 12:36:32
***************
*** 427,440 ****
*/
#if defined(HAVE_MMAP)
! static short_score *scoreboard_image=NULL;
static void setup_shared_mem(void)
{
caddr_t m;
#if defined(MAP_ANON) || defined(MAP_FILE)
/* BSD style */
! m = mmap((caddr_t)0, HARD_SERVER_LIMIT*sizeof(short_score),
PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
if (m == (caddr_t)-1)
{
--- 427,440 ----
*/
#if defined(HAVE_MMAP)
! static scoreboard *scoreboard_image=NULL;
static void setup_shared_mem(void)
{
caddr_t m;
#if defined(MAP_ANON) || defined(MAP_FILE)
/* BSD style */
! m = mmap((caddr_t)0, SCOREBOARD_SIZE,
PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
if (m == (caddr_t)-1)
{
***************
*** 453,459 ****
fprintf(stderr, "httpd: Could not open /dev/zero\n");
exit(1);
}
! m = mmap((caddr_t)0, HARD_SERVER_LIMIT*sizeof(short_score),
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (m == (caddr_t)-1)
{
--- 453,459 ----
fprintf(stderr, "httpd: Could not open /dev/zero\n");
exit(1);
}
! m = mmap((caddr_t)0, SCOREBOARD_SIZE,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (m == (caddr_t)-1)
{
***************
*** 463,486 ****
}
close(fd);
#endif
! scoreboard_image = (short_score *)m;
}
#elif defined(HAVE_SHMGET)
! static short_score *scoreboard_image=NULL;
static key_t shmkey = IPC_PRIVATE;
static int shmid = -1;
static void setup_shared_mem(void)
{
- int score_size = HARD_SERVER_LIMIT*sizeof(short_score);
char errstr[MAX_STRING_LEN];
struct shmid_ds shmbuf;
#ifdef MOVEBREAK
char *obrk;
#endif
! if ((shmid = shmget(shmkey, score_size, IPC_CREAT|SHM_R|SHM_W)) == -1)
{
perror("shmget");
fprintf(stderr, "httpd: Could not call shmget\n");
--- 463,485 ----
}
close(fd);
#endif
! scoreboard_image = (scoreboard *)m;
}
#elif defined(HAVE_SHMGET)
! static scoreboard *scoreboard_image=NULL;
static key_t shmkey = IPC_PRIVATE;
static int shmid = -1;
static void setup_shared_mem(void)
{
char errstr[MAX_STRING_LEN];
struct shmid_ds shmbuf;
#ifdef MOVEBREAK
char *obrk;
#endif
! if ((shmid = shmget(shmkey, SCOREBOARD_SIZE, IPC_CREAT|SHM_R|SHM_W)) == -1)
{
perror("shmget");
fprintf(stderr, "httpd: Could not call shmget\n");
***************
*** 507,514 ****
}
#endif
! #define BADSHMAT ((short_score*)(-1))
! if ((scoreboard_image = (short_score*)shmat(shmid, 0, 0)) == BADSHMAT)
{
perror("shmat");
fprintf(stderr, "httpd: Could not call shmat\n");
--- 506,513 ----
}
#endif
! #define BADSHMAT ((scoreboard *)(-1))
! if ((scoreboard_image = (scoreboard *)shmat(shmid, 0, 0)) == BADSHMAT)
{
perror("shmat");
fprintf(stderr, "httpd: Could not call shmat\n");
***************
*** 557,563 ****
}
#else
! static short_score scoreboard_image[HARD_SERVER_LIMIT];
static int have_scoreboard_fname = 0;
static int scoreboard_fd;
--- 556,563 ----
}
#else
! static scoreboard _scoreboard_image;
! static scoreboard *scoreboard_image=&_scoreboard_image;
static int have_scoreboard_fname = 0;
static int scoreboard_fd;
***************
*** 600,606 ****
{
setup_shared_mem();
}
! memset(scoreboard_image, 0, HARD_SERVER_LIMIT*sizeof(short_score));
#else
scoreboard_fname = server_root_relative (p, scoreboard_fname);
--- 600,606 ----
{
setup_shared_mem();
}
! memset(scoreboard_image, 0, SCOREBOARD_SIZE);
#else
scoreboard_fname = server_root_relative (p, scoreboard_fname);
***************
*** 614,622 ****
exit (1);
}
! memset ((char*)scoreboard_image, 0, sizeof(scoreboard_image));
force_write (scoreboard_fd, (char*)scoreboard_image,
! sizeof(scoreboard_image));
#endif
}
--- 614,622 ----
exit (1);
}
! memset ((char*)scoreboard_image, 0, sizeof(*scoreboard_image));
force_write (scoreboard_fd, (char*)scoreboard_image,
! sizeof(*scoreboard_image));
#endif
}
***************
*** 659,665 ****
#if !defined(HAVE_MMAP) && !defined(HAVE_SHMGET)
lseek (scoreboard_fd, 0L, 0);
force_read (scoreboard_fd, (char*)scoreboard_image,
! sizeof(scoreboard_image));
#endif
}
--- 659,665 ----
#if !defined(HAVE_MMAP) && !defined(HAVE_SHMGET)
lseek (scoreboard_fd, 0L, 0);
force_read (scoreboard_fd, (char*)scoreboard_image,
! sizeof(*scoreboard_image));
#endif
}
***************
*** 671,677 ****
if (child_num < 0)
return -1;
! memcpy(&new_score_rec,&scoreboard_image[child_num],sizeof new_score_rec);
new_score_rec.pid = getpid();
old_status = new_score_rec.status;
new_score_rec.status = status;
--- 671,677 ----
if (child_num < 0)
return -1;
! memcpy(&new_score_rec,&scoreboard_image->servers[child_num],sizeof new_score_rec);
new_score_rec.pid = getpid();
old_status = new_score_rec.status;
new_score_rec.status = status;
***************
*** 702,708 ****
#endif
#if defined(HAVE_MMAP) || defined(HAVE_SHMGET)
! memcpy(&scoreboard_image[child_num], &new_score_rec, sizeof(short_score));
#else
lseek (scoreboard_fd, (long)child_num * sizeof(short_score), 0);
force_write (scoreboard_fd, (char*)&new_score_rec, sizeof(short_score));
--- 702,708 ----
#endif
#if defined(HAVE_MMAP) || defined(HAVE_SHMGET)
! memcpy(&scoreboard_image->servers[child_num], &new_score_rec, sizeof new_score_rec);
#else
lseek (scoreboard_fd, (long)child_num * sizeof(short_score), 0);
force_write (scoreboard_fd, (char*)&new_score_rec, sizeof(short_score));
***************
*** 711,722 ****
return old_status;
}
int get_child_status (int child_num)
{
if (child_num<0 || child_num>=HARD_SERVER_LIMIT)
return -1;
else
! return scoreboard_image[child_num].status;
}
int count_busy_servers ()
--- 711,732 ----
return old_status;
}
+ void update_scoreboard_global()
+ {
+ #if !defined(HAVE_MMAP) && !defined(HAVE_SHMGET)
+ lseek(scoreboard_fd,
+ (char *)&scoreboard_image->global-(char *)scoreboard_image,0);
+ force_write(scoreboard_fd,(char *)&scoreboard_image->global,
+ sizeof scoreboard_image->global);
+ #endif
+ }
+
int get_child_status (int child_num)
{
if (child_num<0 || child_num>=HARD_SERVER_LIMIT)
return -1;
else
! return scoreboard_image->servers[child_num].status;
}
int count_busy_servers ()
***************
*** 725,742 ****
int res = 0;
for (i = 0; i < HARD_SERVER_LIMIT; ++i)
! if (scoreboard_image[i].status == SERVER_BUSY_READ ||
! scoreboard_image[i].status == SERVER_BUSY_WRITE ||
! scoreboard_image[i].status == SERVER_BUSY_KEEPALIVE ||
! scoreboard_image[i].status == SERVER_BUSY_LOG ||
! scoreboard_image[i].status == SERVER_BUSY_DNS)
++res;
return res;
}
short_score get_scoreboard_info(int i)
{
! return (scoreboard_image[i]);
}
#if defined(STATUS)
--- 735,763 ----
int res = 0;
for (i = 0; i < HARD_SERVER_LIMIT; ++i)
! if (scoreboard_image->servers[i].status == SERVER_BUSY_READ ||
! scoreboard_image->servers[i].status == SERVER_BUSY_WRITE ||
! scoreboard_image->servers[i].status == SERVER_BUSY_KEEPALIVE ||
! scoreboard_image->servers[i].status == SERVER_BUSY_LOG ||
! scoreboard_image->servers[i].status == SERVER_BUSY_DNS)
++res;
return res;
}
+ int count_live_servers()
+ {
+ int i;
+ int res = 0;
+
+ for (i = 0; i < HARD_SERVER_LIMIT; ++i)
+ if (scoreboard_image->servers[i].status != SERVER_DEAD)
+ ++res;
+ return res;
+ }
+
short_score get_scoreboard_info(int i)
{
! return (scoreboard_image->servers[i]);
}
#if defined(STATUS)
***************
*** 776,783 ****
int res = 0;
for (i = 0; i < HARD_SERVER_LIMIT; ++i)
! if (scoreboard_image[i].status == SERVER_READY
! || scoreboard_image[i].status == SERVER_STARTING)
++res;
return res;
--- 797,804 ----
int res = 0;
for (i = 0; i < HARD_SERVER_LIMIT; ++i)
! if (scoreboard_image->servers[i].status == SERVER_READY
! || scoreboard_image->servers[i].status == SERVER_STARTING)
++res;
return res;
***************
*** 788,794 ****
int i;
for (i = 0; i < HARD_SERVER_LIMIT; ++i)
! if (scoreboard_image[i].status == SERVER_DEAD)
return i;
return -1;
--- 809,815 ----
int i;
for (i = 0; i < HARD_SERVER_LIMIT; ++i)
! if (scoreboard_image->servers[i].status == SERVER_DEAD)
return i;
return -1;
***************
*** 799,805 ****
int i;
for (i = 0; i < HARD_SERVER_LIMIT; ++i)
! if (scoreboard_image[i].pid == pid)
return i;
return -1;
--- 820,826 ----
int i;
for (i = 0; i < HARD_SERVER_LIMIT; ++i)
! if (scoreboard_image->servers[i].pid == pid)
return i;
return -1;
***************
*** 812,821 ****
sync_scoreboard_image();
for (i = 0; i < HARD_SERVER_LIMIT; ++i) {
! int pid = scoreboard_image[i].pid;
if (pid != my_pid && pid != 0)
! waitpid (scoreboard_image[i].pid, &status, 0);
}
}
--- 833,842 ----
sync_scoreboard_image();
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);
}
}
***************
*** 994,999 ****
--- 1015,1026 ----
#endif
}
+ void graceful_restart()
+ {
+ scoreboard_image->global.please_exit=1;
+ update_scoreboard_global();
+ }
+
void set_signals() {
#ifndef NO_USE_SIGACTION
struct sigaction sa;
***************
*** 1006,1011 ****
--- 1033,1039 ----
#ifdef NO_USE_SIGACTION
signal(SIGTERM,(void (*)())sig_term);
signal(SIGHUP,(void (*)())restart);
+ signal(SIGINT,(void (*)())graceful_restart);
#else
memset(&sa,0,sizeof sa);
sa.sa_handler=(void (*)())sig_term;
***************
*** 1014,1019 ****
--- 1042,1050 ----
sa.sa_handler=(void (*)())restart;
if(sigaction(SIGHUP,&sa,NULL) < 0)
log_unixerr("sigaction(SIGHUP)", NULL, NULL, server_conf);
+ sa.sa_handler=(void (*)())graceful_restart;
+ if(sigaction(SIGINT,&sa,NULL) < 0)
+ log_unixerr("sigaction(SIGINT)", NULL, NULL, server_conf);
#endif
}
***************
*** 1166,1171 ****
--- 1197,1205 ----
clear_pool (ptrans);
sync_scoreboard_image();
+
+ if(scoreboard_image->global.please_exit)
+ exit(0);
if ((count_idle_servers() >= daemons_max_free)
|| (max_requests_per_child > 0
***************
*** 1250,1255 ****
--- 1284,1293 ----
#if defined(STATUS)
if (r) increment_counts(child_num,r,0);
#endif
+ sync_scoreboard_image();
+ if(scoreboard_image->global.please_exit)
+ exit(0);
+
}
#if 0
if (bytes_in_pool (ptrans) > 80000)
***************
*** 1445,1457 ****
}
sync_scoreboard_image();
! if ((count_idle_servers() < daemons_min_free)
&& (child_slot = find_free_child_num()) >= 0
&& child_slot <= daemons_limit) {
(void)update_child_status(child_slot,SERVER_STARTING,
(request_rec*)NULL);
make_child(server_conf, child_slot);
}
}
} /* standalone_main */
--- 1483,1505 ----
}
sync_scoreboard_image();
! if (!scoreboard_image->global.please_exit
! && (count_idle_servers() < daemons_min_free)
&& (child_slot = find_free_child_num()) >= 0
&& child_slot <= daemons_limit) {
(void)update_child_status(child_slot,SERVER_STARTING,
(request_rec*)NULL);
make_child(server_conf, child_slot);
+
}
+
+ if(scoreboard_image->global.please_exit && !count_live_servers())
+ #ifdef NEXT
+ longjmp(restart_buffer,1);
+ #else
+ siglongjmp(restart_buffer,1);
+ #endif
+
}
} /* standalone_main */
Index: scoreboard.h
===================================================================
RCS file: /export/home/cvs/apache/src/scoreboard.h,v
retrieving revision 1.12
diff -c -r1.12 scoreboard.h
*** scoreboard.h 1996/06/07 17:39:26 1.12
--- scoreboard.h 1996/06/23 12:36:33
***************
*** 90,94 ****
--- 90,109 ----
#endif
} short_score;
+ typedef struct
+ {
+ char please_exit; /* Set by the main process if a graceful
+ restart is required */
+ } global_score;
+
+ typedef struct
+ {
+ short_score servers[HARD_SERVER_LIMIT];
+ global_score global;
+ } scoreboard;
+
+ #define SCOREBOARD_SIZE sizeof(scoreboard)
+
extern void sync_scoreboard_image(void);
short_score get_scoreboard_info(int x);
+
--
Ben Laurie Phone: +44 (181) 994 6435
Freelance Consultant and Fax: +44 (181) 994 6472
Technical Director Email: ben@algroup.co.uk
A.L. Digital Ltd, URL: http://www.algroup.co.uk
London, England.