Pantek Library
Hosting Provided By
CybrHost
High Speed Hosting

"Graceful Restart" patch

From: Ben Laurie <ben(at)gonzo.ben.algroup.co.uk>
Date: Sun Jun 23 1996 - 08:02:24 EDT


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 ----
Do you need help?X

   */   

#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 **** }
Do you need more help?X

#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,
Can we help you?X
! 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;
Don't know where to look next?X
return res;

  }   
Can't find what you're looking for?X

  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) {
Confused? Frustrated?X
! 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
+
Call Pantek today for Open Source Technical Support at 1-877-546-8934 - 24/7/365X

      }   

  } /* 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];
Do you need help?X
+ 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.
Received on Sun Jun 23 05:45:59 1996

This archive was generated by hypermail 2.1.8 : Thu Aug 24 2006 - 14:43:43 EDT


Contact Us  Legal Notices  Order Services Online 
Pantek Home  Privacy Policy  IT news  Site Map  Pantek Library