manoj       99/02/09 23:59:40

  Modified:    pthreads/src/main http_main.c
  Log:
  Two pieces that are closely intertwined (or at least seem to be at 3AM).
  First, there is now a means for the parent to kill off a child process
  at will. One thread is assigned the duty of listening to signals and
  responding to them.
  
  Second, the beginnings of proper signal handling. SIGTERM is mostly
  working. The others shouldn't be too far off, hopefully.
  
  Revision  Changes    Path
  1.14      +495 -18   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.13
  retrieving revision 1.14
  diff -u -u -r1.13 -r1.14
  --- http_main.c       1999/02/10 07:24:34     1.13
  +++ http_main.c       1999/02/10 07:59:39     1.14
  @@ -487,6 +487,7 @@
        ap_destroy_pool(pchild);
       }
       /*    longjump(tls()->thread_exit, 1); */
  +    exit(code);
   }
   
   static void usage(char *bin)
  @@ -940,10 +941,342 @@
       return -1;
   }
   
  +static void reclaim_child_processes(int terminate)
  +{
  +    int i, status;
  +    long int waittime = 1024 * 16;   /* in usecs */
  +    struct timeval tv;
  +    int waitret, tries;
  +    int not_dead_yet;
  +#ifndef NO_OTHER_CHILD
  +    other_child_rec *ocr, *nocr;
  +#endif
  +
  +    ap_sync_scoreboard_image();
  +
  +    for (tries = terminate ? 4 : 1; tries <= 9; ++tries) {
  +     /* don't want to hold up progress any more than 
  +      * necessary, but we need to allow children a few moments to exit.
  +      * Set delay with an exponential backoff.
  +      */
  +     tv.tv_sec = waittime / 1000000;
  +     tv.tv_usec = waittime % 1000000;
  +     waittime = waittime * 4;
  +     ap_select(0, NULL, NULL, NULL, &tv);
  +
  +     /* now see who is done */
  +     not_dead_yet = 0;
  +     for (i = 0; i < max_daemons_limit; ++i) {
  +         int pid = ap_scoreboard_image->parent[i].pid;
  +
  +         if (pid == my_pid || pid == 0)
  +             continue;
  +
  +         waitret = waitpid(pid, &status, WNOHANG);
  +         if (waitret == pid || waitret == -1) {
  +             ap_scoreboard_image->parent[i].pid = 0;
  +             continue;
  +         }
  +         ++not_dead_yet;
  +         switch (tries) {
  +         case 1:     /*  16ms */
  +         case 2:     /*  82ms */
  +             break;
  +         case 3:     /* 344ms */
  +             /* perhaps it missed the SIGHUP, lets try again */
  +             ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
  +                         server_conf,
  +                 "child process %d did not exit, sending another SIGHUP",
  +                         pid);
  +             kill(pid, SIGHUP);
  +             waittime = 1024 * 16;
  +             break;
  +         case 4:     /*  16ms */
  +         case 5:     /*  82ms */
  +         case 6:     /* 344ms */
  +             break;
  +         case 7:     /* 1.4sec */
  +             /* ok, now it's being annoying */
  +             ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
  +                         server_conf,
  +                "child process %d still did not exit, sending a SIGTERM",
  +                         pid);
  +             kill(pid, SIGTERM);
  +             break;
  +         case 8:     /*  6 sec */
  +             /* die child scum */
  +             ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, server_conf,
  +                "child process %d still did not exit, sending a SIGKILL",
  +                         pid);
  +             kill(pid, SIGKILL);
  +             break;
  +         case 9:     /* 14 sec */
  +             /* gave it our best shot, but alas...  If this really 
  +              * is a child we are trying to kill and it really hasn't
  +              * exited, we will likely fail to bind to the port
  +              * after the restart.
  +              */
  +             ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, server_conf,
  +                         "could not make child process %d exit, "
  +                         "attempting to continue anyway", pid);
  +             break;
  +         }
  +     }
  +#ifndef NO_OTHER_CHILD
  +     for (ocr = other_children; ocr; ocr = nocr) {
  +         nocr = ocr->next;
  +         if (ocr->pid == -1)
  +             continue;
  +
  +         waitret = waitpid(ocr->pid, &status, WNOHANG);
  +         if (waitret == ocr->pid) {
  +             ocr->pid = -1;
  +             (*ocr->maintenance) (OC_REASON_DEATH, ocr->data, status);
  +         }
  +         else if (waitret == 0) {
  +             (*ocr->maintenance) (OC_REASON_RESTART, ocr->data, -1);
  +             ++not_dead_yet;
  +         }
  +         else if (waitret == -1) {
  +             /* uh what the heck? they didn't call unregister? */
  +             ocr->pid = -1;
  +             (*ocr->maintenance) (OC_REASON_LOST, ocr->data, -1);
  +         }
  +     }
  +#endif
  +     if (!not_dead_yet) {
  +         /* nothing left to wait for */
  +         break;
  +     }
  +    }
  +}
  +
  +/* Finally, this routine is used by the caretaker process to wait for
  + * a while...
  + */
  +
  +/* number of calls to wait_or_timeout between writable probes */
  +#ifndef INTERVAL_OF_WRITABLE_PROBES
  +#define INTERVAL_OF_WRITABLE_PROBES 10
  +#endif
  +static int wait_or_timeout_counter;
  +
  +static int wait_or_timeout(ap_wait_t *status)
  +{
  +    struct timeval tv;
  +    int ret;
  +
  +    ++wait_or_timeout_counter;
  +    if (wait_or_timeout_counter == INTERVAL_OF_WRITABLE_PROBES) {
  +     wait_or_timeout_counter = 0;
  +#ifndef NO_OTHER_CHILD
  +     probe_writable_fds();
  +#endif
  +    }
  +    ret = waitpid(-1, status, WNOHANG);
  +    if (ret == -1 && errno == EINTR) {
  +     return -1;
  +    }
  +    if (ret > 0) {
  +     return ret;
  +    }
  +#ifdef NEED_WAITPID
  +    if ((ret = reap_children(status)) > 0) {
  +     return ret;
  +    }
  +#endif
  +    tv.tv_sec = SCOREBOARD_MAINTENANCE_INTERVAL / 1000000;
  +    tv.tv_usec = SCOREBOARD_MAINTENANCE_INTERVAL % 1000000;
  +    ap_select(0, NULL, NULL, NULL, &tv);
  +    return -1;
  +}
  +
  +#if defined(NSIG)
  +#define NumSIG NSIG
  +#elif defined(_NSIG)
  +#define NumSIG _NSIG
  +#elif defined(__NSIG)
  +#define NumSIG __NSIG
  +#else
  +#define NumSIG 32   /* for 1998's unixes, this is still a good assumption */
  +#endif
  +
  +#ifdef SYS_SIGLIST /* platform has sys_siglist[] */
  +#define INIT_SIGLIST()  /*nothing*/
  +#else /* platform has no sys_siglist[], define our own */
  +#define SYS_SIGLIST ap_sys_siglist
  +#define INIT_SIGLIST() siglist_init();
  +
  +const char *ap_sys_siglist[NumSIG];
  +
  +static void siglist_init(void)
  +{
  +    int sig;
  +
  +    ap_sys_siglist[0] = "Signal 0";
  +#ifdef SIGHUP
  +    ap_sys_siglist[SIGHUP] = "Hangup";
  +#endif
  +#ifdef SIGINT
  +    ap_sys_siglist[SIGINT] = "Interrupt";
  +#endif
  +#ifdef SIGQUIT
  +    ap_sys_siglist[SIGQUIT] = "Quit";
  +#endif
  +#ifdef SIGILL
  +    ap_sys_siglist[SIGILL] = "Illegal instruction";
  +#endif
  +#ifdef SIGTRAP
  +    ap_sys_siglist[SIGTRAP] = "Trace/BPT trap";
  +#endif
  +#ifdef SIGIOT
  +    ap_sys_siglist[SIGIOT] = "IOT instruction";
  +#endif
  +#ifdef SIGABRT
  +    ap_sys_siglist[SIGABRT] = "Abort";
  +#endif
  +#ifdef SIGEMT
  +    ap_sys_siglist[SIGEMT] = "Emulator trap";
  +#endif
  +#ifdef SIGFPE
  +    ap_sys_siglist[SIGFPE] = "Arithmetic exception";
  +#endif
  +#ifdef SIGKILL
  +    ap_sys_siglist[SIGKILL] = "Killed";
  +#endif
  +#ifdef SIGBUS
  +    ap_sys_siglist[SIGBUS] = "Bus error";
  +#endif
  +#ifdef SIGSEGV
  +    ap_sys_siglist[SIGSEGV] = "Segmentation fault";
  +#endif
  +#ifdef SIGSYS
  +    ap_sys_siglist[SIGSYS] = "Bad system call";
  +#endif
  +#ifdef SIGPIPE
  +    ap_sys_siglist[SIGPIPE] = "Broken pipe";
  +#endif
  +#ifdef SIGALRM
  +    ap_sys_siglist[SIGALRM] = "Alarm clock";
  +#endif
  +#ifdef SIGTERM
  +    ap_sys_siglist[SIGTERM] = "Terminated";
  +#endif
  +#ifdef SIGUSR1
  +    ap_sys_siglist[SIGUSR1] = "User defined signal 1";
  +#endif
  +#ifdef SIGUSR2
  +    ap_sys_siglist[SIGUSR2] = "User defined signal 2";
  +#endif
  +#ifdef SIGCLD
  +    ap_sys_siglist[SIGCLD] = "Child status change";
  +#endif
  +#ifdef SIGCHLD
  +    ap_sys_siglist[SIGCHLD] = "Child status change";
  +#endif
  +#ifdef SIGPWR
  +    ap_sys_siglist[SIGPWR] = "Power-fail restart";
  +#endif
  +#ifdef SIGWINCH
  +    ap_sys_siglist[SIGWINCH] = "Window changed";
  +#endif
  +#ifdef SIGURG
  +    ap_sys_siglist[SIGURG] = "urgent socket condition";
  +#endif
  +#ifdef SIGPOLL
  +    ap_sys_siglist[SIGPOLL] = "Pollable event occurred";
  +#endif
  +#ifdef SIGIO
  +    ap_sys_siglist[SIGIO] = "socket I/O possible";
  +#endif
  +#ifdef SIGSTOP
  +    ap_sys_siglist[SIGSTOP] = "Stopped (signal)";
  +#endif
  +#ifdef SIGTSTP
  +    ap_sys_siglist[SIGTSTP] = "Stopped";
  +#endif
  +#ifdef SIGCONT
  +    ap_sys_siglist[SIGCONT] = "Continued";
  +#endif
  +#ifdef SIGTTIN
  +    ap_sys_siglist[SIGTTIN] = "Stopped (tty input)";
  +#endif
  +#ifdef SIGTTOU
  +    ap_sys_siglist[SIGTTOU] = "Stopped (tty output)";
  +#endif
  +#ifdef SIGVTALRM
  +    ap_sys_siglist[SIGVTALRM] = "virtual timer expired";
  +#endif
  +#ifdef SIGPROF
  +    ap_sys_siglist[SIGPROF] = "profiling timer expired";
  +#endif
  +#ifdef SIGXCPU
  +    ap_sys_siglist[SIGXCPU] = "exceeded cpu limit";
  +#endif
  +#ifdef SIGXFSZ
  +    ap_sys_siglist[SIGXFSZ] = "exceeded file size limit";
  +#endif
  +    for (sig=0; sig < sizeof(ap_sys_siglist)/sizeof(ap_sys_siglist[0]); 
++sig)
  +        if (ap_sys_siglist[sig] == NULL)
  +            ap_sys_siglist[sig] = "";
  +}
  +#endif /* platform has sys_siglist[] */
  +
  +/* handle all varieties of core dumping signals */
  +static void sig_coredump(int sig)
  +{
  +    chdir(ap_coredump_dir);
  +    signal(sig, SIG_DFL);
  +#ifndef WIN32
  +    kill(getpid(), sig);
  +#else
  +    raise(sig);
  +#endif
  +    /* At this point we've got sig blocked, because we're still inside
  +     * the signal handler.  When we leave the signal handler it will
  +     * be unblocked, and we'll take the signal... and coredump or whatever
  +     * is appropriate for this particular Unix.  In addition the parent
  +     * will see the real signal we received -- whereas if we called
  +     * abort() here, the parent would only see SIGABRT.
  +     */
  +}
  +
   /*****************************************************************
    * Connection structures and accounting...
    */
   
  +/* XXX - alarms will need to be blockable at some point */
  +
  +static int alarms_blocked = 0;
  +static int exit_after_unblock = 0;
  +static void just_die(int sig)
  +{                            /* SIGHUP to child process??? */
  +    /* if alarms are blocked we have to wait to die otherwise we might
  +     * end up with corruption in alloc.c's internal structures */
  +    if (alarms_blocked) {
  +     exit_after_unblock = 1;
  +    }
  +    else {
  +     clean_child_exit(0);
  +    }
  +}
  +
  +static int volatile usr1_just_die = 1;
  +static int volatile deferred_die;
  +
  +static void usr1_handler(int sig)
  +{
  +    if (usr1_just_die) {
  +     just_die(sig);
  +    }
  +    deferred_die = 1;
  +}
  +
  +
  +/*****************************************************************
  + * Connection structures and accounting...
  + */
  +
   /* volatile just in case */
   static int volatile shutdown_pending;
   static int volatile restart_pending;
  @@ -992,15 +1325,119 @@
       is_graceful = graceful;
   }
   
  -static void set_signals(void)
  +static void sig_term(int sig)
   {
  +    ap_start_shutdown();
  +}
   
  -#ifdef SIGPIPE
  -    signal(SIGPIPE, SIG_IGN);
  +static void restart(int sig)
  +{
  +#ifndef WIN32
  +    ap_start_restart(sig == SIGUSR1);
  +#else
  +    ap_start_restart(1);
   #endif
  -    /* ZZZ: what signals do we need to configure? */
   }
   
  +static void set_signals(void)
  +{
  +#ifndef NO_USE_SIGACTION
  +    struct sigaction sa;
  +
  +    sigemptyset(&sa.sa_mask);
  +    sa.sa_flags = 0;
  +
  +    if (!one_process) {
  +     sa.sa_handler = sig_coredump;
  +#if defined(SA_ONESHOT)
  +     sa.sa_flags = SA_ONESHOT;
  +#elif defined(SA_RESETHAND)
  +     sa.sa_flags = SA_RESETHAND;
  +#endif
  +     if (sigaction(SIGSEGV, &sa, NULL) < 0)
  +         ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, 
"sigaction(SIGSEGV)");
  +#ifdef SIGBUS
  +     if (sigaction(SIGBUS, &sa, NULL) < 0)
  +         ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, 
"sigaction(SIGBUS)");
  +#endif
  +#ifdef SIGABORT
  +     if (sigaction(SIGABORT, &sa, NULL) < 0)
  +         ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, 
"sigaction(SIGABORT)");
  +#endif
  +#ifdef SIGABRT
  +     if (sigaction(SIGABRT, &sa, NULL) < 0)
  +         ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, 
"sigaction(SIGABRT)");
  +#endif
  +#ifdef SIGILL
  +     if (sigaction(SIGILL, &sa, NULL) < 0)
  +         ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, 
"sigaction(SIGILL)");
  +#endif
  +     sa.sa_flags = 0;
  +    }
  +    sa.sa_handler = sig_term;
  +    if (sigaction(SIGTERM, &sa, NULL) < 0)
  +     ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, 
"sigaction(SIGTERM)");
  +#ifdef SIGINT
  +    if (sigaction(SIGINT, &sa, NULL) < 0)
  +        ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, 
"sigaction(SIGINT)");
  +#endif
  +#ifdef SIGXCPU
  +    sa.sa_handler = SIG_DFL;
  +    if (sigaction(SIGXCPU, &sa, NULL) < 0)
  +     ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, 
"sigaction(SIGXCPU)");
  +#endif
  +#ifdef SIGXFSZ
  +    sa.sa_handler = SIG_DFL;
  +    if (sigaction(SIGXFSZ, &sa, NULL) < 0)
  +     ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, 
"sigaction(SIGXFSZ)");
  +#endif
  +
  +    /* we want to ignore HUPs and USR1 while we're busy processing one */
  +    sigaddset(&sa.sa_mask, SIGHUP);
  +#ifndef LINUX
  +    sigaddset(&sa.sa_mask, SIGUSR1);
  +#endif /* LINUX */
  +    sa.sa_handler = restart;
  +    if (sigaction(SIGHUP, &sa, NULL) < 0)
  +     ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, 
"sigaction(SIGHUP)");
  +#ifndef LINUX
  +    if (sigaction(SIGUSR1, &sa, NULL) < 0)
  +     ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, 
"sigaction(SIGUSR1)");
  +#endif /* LINUX */
  +#else
  +    if (!one_process) {
  +     signal(SIGSEGV, sig_coredump);
  +#ifdef SIGBUS
  +     signal(SIGBUS, sig_coredump);
  +#endif /* SIGBUS */
  +#ifdef SIGABORT
  +     signal(SIGABORT, sig_coredump);
  +#endif /* SIGABORT */
  +#ifdef SIGABRT
  +     signal(SIGABRT, sig_coredump);
  +#endif /* SIGABRT */
  +#ifdef SIGILL
  +     signal(SIGILL, sig_coredump);
  +#endif /* SIGILL */
  +#ifdef SIGXCPU
  +     signal(SIGXCPU, SIG_DFL);
  +#endif /* SIGXCPU */
  +#ifdef SIGXFSZ
  +     signal(SIGXFSZ, SIG_DFL);
  +#endif /* SIGXFSZ */
  +    }
  +
  +    signal(SIGTERM, sig_term);
  +#ifdef SIGHUP
  +    signal(SIGHUP, restart);
  +#endif /* SIGHUP */
  +#ifndef LINUX
  +#ifdef SIGUSR1
  +    signal(SIGUSR1, restart);
  +#endif /* SIGUSR1 */
  +#endif /* LINUX */
  +#endif
  +}
   
   /*****************************************************************
    * Here follows a long bunch of generic server bookkeeping stuff...
  @@ -1767,6 +2204,9 @@
       pthread_t thread;
       int my_child_num = child_num_arg;
       proc_info *my_info = NULL;
  +    sigset_t sig_mask;
  +    int ret;
  +    pthread_attr_t thread_attr = PTHREAD_COND_INITIALIZER;
   
       my_pid = getpid();
       requests_this_child = 0;
  @@ -1791,6 +2231,17 @@
   
       queue_init(&csd_queue, ap_threads_per_child);
   
  +    /* We don't want to have to pthread_wait on these threads */
  +    pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
  +    /* Set signal masks for threads to basically nothing */
  +    sigemptyset(&sig_mask);
  +#ifdef LINUX
  +    sigaddset(&sig_mask, SIGUSR1);
  +    sigaddset(&sig_mask, SIGUSR2);
  +#endif
  +    if ((ret = pthread_sigmask(SIG_SETMASK, &sig_mask, NULL)) != 0) {
  +        ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf, "pthread_sigmask 
failed");
  +    }
       /* Setup worker threads */
       for (i=0; i < ap_threads_per_child; i++) {
           my_info = NULL;
  @@ -1804,7 +2255,7 @@
        (void) ap_update_child_status(my_child_num, i, SERVER_STARTING, 
                                      (request_rec *) NULL);
        
  -     if (pthread_create(&thread, NULL, worker_thread, my_info)) {
  +     if (pthread_create(&thread, &thread_attr, worker_thread, my_info)) {
            ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
                         "pthread_create: unable to create worker thread");
            /* 
  @@ -1819,6 +2270,7 @@
         * because it let's us deal with tid better.
         */
       }    
  +
       /* Setup acceptor threads */
       
       lr = ap_listeners;
  @@ -1830,7 +2282,7 @@
           my_info->tid = i++;
        my_info->sd = lr->fd;
   
  -     if (pthread_create(&thread, NULL, accept_thread, my_info)) {
  +     if (pthread_create(&thread, &thread_attr, accept_thread, my_info)) {
          ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf,
                       "pthread_create: unable to create acceptor thread");
          /* 
  @@ -1845,6 +2297,11 @@
        }
        lr = lr->next;
       }
  +    /* This thread will be the one responsible for handling signals */
  +    sigfillset(&sig_mask);
  +    if ((ret = pthread_sigmask(SIG_SETMASK, &sig_mask, NULL)) != 0) {
  +        ap_log_error(APLOG_MARK, APLOG_ALERT, server_conf, "pthread_sigmask 
failed");
  +    }
       my_info = NULL;
       
       my_info = (proc_info *)malloc(sizeof(proc_info));
  @@ -1879,7 +2336,7 @@
       }
   
       if (one_process) {
  -        set_signals();
  +     set_signals();
        child_main(slot);
       }
   
  @@ -1914,14 +2371,15 @@
   
           RAISE_SIGSTOP(MAKE_CHILD);
           MONCONTROL(1);
  -     set_signals();
  -    
  -     child_main(slot);
   
  -     ap_scoreboard_image->parent[slot].pid = pid;
  +        signal(SIGHUP, just_die);
  +        signal(SIGTERM, just_die);
  +     child_main(slot);
   
        return 0;
       }
  +    /* else */
  +    ap_scoreboard_image->parent[slot].pid = pid;
   }
   
   /* start up a bunch of children */
  @@ -2079,14 +2537,14 @@
   static void server_main_loop(int remaining_children_to_start)
   {
       int child_slot;
  -    int status;
  +    ap_wait_t status;
       int pid;
   
       head_listener = ap_listeners;
   
       while (!restart_pending && !shutdown_pending) {
         sleep(10); /* ZZZZ how long? 10000 intervals */
  -        pid = -1;
  +        pid = wait_or_timeout(&status);
           
           if (pid >= 0) {
               child_slot = find_child_by_pid(0);
  @@ -2167,7 +2625,7 @@
        reinit_scoreboard(pconf);
       }
   
  -
  +    set_signals();
       /* set up get_socket */
       head_listener = ap_listeners;
   
  @@ -2209,12 +2667,33 @@
       server_main_loop(remaining_children_to_start);
   
       if (shutdown_pending) {
  -      /* ZZZZ Thread cleanup */
  -
  +        /* Time to gracefully shut down:
  +         * Kill child processes, tell them to call child_exit, etc...
  +         */
  +        if (ap_killpg(pgrp, SIGTERM) < 0) {
  +            ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "killpg 
SIGTERM");
  +        }
  +        reclaim_child_processes(1);          /* Start with SIGTERM */
  +    
  +        /* cleanup pid file on normal shutdown */
  +        {
  +            const char *pidfile = NULL;
  +            pidfile = ap_server_root_relative (pconf, ap_pid_fname);
  +            if ( pidfile != NULL && unlink(pidfile) == 0)
  +                ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO,
  +                      server_conf,
  +                      "removed PID file %s (pid=%ld)",
  +                      pidfile, (long)getpid());
  +        }
  +    
  +        ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf,
  +            "caught SIGTERM, shutting down");
  +    
           clean_parent_exit(0);
       }
   
       /* we've been told to restart */
  +    signal(SIGHUP, SIG_IGN);
   
       if (one_process) {
        /* not worth thinking about */
  @@ -2257,11 +2736,9 @@
       }
       else {
        /* Kill 'em all */
  -#if 0
        if (ap_killpg(pgrp, SIGHUP) < 0) {
            ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, "killpg 
SIGHUP");
        }
  -#endif
        ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf,
                    "SIGHUP received.  Attempting to restart");
       }
  
  
  

Reply via email to