Changeset 4d6b73a5f96a33b3f51a2d1d7d8c58779d980f0d

Show
Ignore:
Timestamp:
07/23/08 16:03:53 (6 years ago)
Author:
Theo Schlossnagle <jesus@omniti.com>
git-committer:
Theo Schlossnagle <jesus@omniti.com> 1216829033 +0000
git-parent:

[5299b95492a1e76085ae34cf08f96ba288e9b86f]

git-author:
Theo Schlossnagle <jesus@omniti.com> 1216829033 +0000
Message:

closes #48

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/noit_console.h

    r4cdbcdb r4d6b73a  
    3434/* This performs a pop (exiting if at toplevel) */ 
    3535extern cmd_info_t console_command_exit; 
     36extern cmd_info_t console_command_shutdown; 
     37extern cmd_info_t console_command_restart; 
    3638 
    3739typedef struct { 
     
    118120 
    119121API_EXPORT(int) 
     122  noit_console_shutdown(noit_console_closure_t ncct, int argc, char **argv, 
     123                        noit_console_state_t *, void *); 
     124 
     125API_EXPORT(int) 
     126  noit_console_restart(noit_console_closure_t ncct, int argc, char **argv, 
     127                       noit_console_state_t *, void *); 
     128 
     129API_EXPORT(int) 
    120130  noit_console_state_add_cmd(noit_console_state_t *state, 
    121131                             cmd_info_t *cmd); 
  • src/noit_console_state.c

    rde852c9 r4d6b73a  
    2020  "exit", noit_console_state_pop, NULL, NULL 
    2121}; 
     22cmd_info_t console_command_shutdown = { 
     23  "shutdown", noit_console_shutdown, NULL, NULL 
     24}; 
     25cmd_info_t console_command_restart = { 
     26  "restart", noit_console_restart, NULL, NULL 
     27}; 
     28 
    2229 
    2330static char * 
     
    337344    noit_console_state_add_cmd(_top_level_state, 
    338345      NCSCMD("show", noit_console_state_delegate, show_state, NULL)); 
     346    noit_console_state_add_cmd(_top_level_state, &console_command_shutdown); 
     347    noit_console_state_add_cmd(_top_level_state, &console_command_restart); 
    339348  } 
    340349  return _top_level_state; 
     
    352361 
    353362int 
     363noit_console_shutdown(noit_console_closure_t ncct, int argc, char **argv, 
     364                      noit_console_state_t *dstate, void *unused) { 
     365  exit(2); 
     366} 
     367int 
     368noit_console_restart(noit_console_closure_t ncct, int argc, char **argv, 
     369                     noit_console_state_t *dstate, void *unused) { 
     370  exit(1); 
     371} 
     372 
     373int 
    354374noit_console_state_pop(noit_console_closure_t ncct, int argc, char **argv, 
    355375                       noit_console_state_t *dstate, void *unused) { 
  • src/noitd.c

    rdcd539d r4d6b73a  
    77#include <sys/ioctl.h> 
    88#include <fcntl.h> 
     9#include <sys/mman.h> 
     10#include <signal.h> 
    911 
    1012#include "eventer/eventer.h" 
     
    2022 
    2123#define APPNAME "noit" 
     24#define CHILD_WATCHDOG_TIMEOUT 5 /*seconds*/ 
    2225 
    2326static char *config_file = ETC_DIR "/" APPNAME ".conf"; 
     
    6063} 
    6164 
     65/* Watchdog stuff */ 
     66static int *lifeline = NULL; 
     67static unsigned long last_tick_time() { 
     68  static struct timeval lastchange = { 0, 0 }; 
     69  static int lastcheck = 0; 
     70  struct timeval now, diff; 
     71 
     72  gettimeofday(&now, NULL); 
     73  if(lastcheck != *lifeline) { 
     74    lastcheck = *lifeline; 
     75    memcpy(&lastchange, &now, sizeof(lastchange)); 
     76  } 
     77  sub_timeval(now, lastchange, &diff); 
     78  return (unsigned long)diff.tv_sec; 
     79} 
     80static void it_ticks() { 
     81  (*lifeline)++; 
     82} 
     83static void setup_mmap() { 
     84  lifeline = mmap(NULL, sizeof(int), PROT_READ|PROT_WRITE, 
     85                  MAP_SHARED|MAP_ANON, -1, 0); 
     86  if(lifeline == (void *)-1) { 
     87    noitL(noit_error, "Failed to mmap anon for watchdog\n"); 
     88    exit(-1); 
     89  } 
     90} 
     91 
     92static int watch_over_child(int (*func)()) { 
     93  int child_pid; 
     94  setup_mmap(); 
     95  while(1) { 
     96    child_pid = fork(); 
     97    if(child_pid == -1) { 
     98      noitL(noit_error, "fork failed: %s\n", strerror(errno)); 
     99      exit(-1); 
     100    } 
     101    if(child_pid == 0) { 
     102      /* This sets up things so we start alive */ 
     103      it_ticks(); 
     104      /* run the program */ 
     105      exit(func()); 
     106    } 
     107    else { 
     108      int sig = -1, exit_val = -1; 
     109      while(1) { 
     110        unsigned long ltt; 
     111        int status, rv; 
     112        sleep(1); /* Just check child status every second */ 
     113        rv = waitpid(child_pid, &status, WNOHANG); 
     114        if(rv == 0) { 
     115          /* Nothing */ 
     116        } 
     117        else if (rv == child_pid) { 
     118          /* We died!... we need to relaunch, unless the status was a requested exit (2) */ 
     119          sig = WTERMSIG(status); 
     120          exit_val = WEXITSTATUS(status); 
     121          if(sig == SIGINT || sig == SIGQUIT || 
     122             (sig == 0 && (exit_val == 2 || exit_val < 0))) { 
     123            noitL(noit_error, "noitd shutdown acknowledged.\n"); 
     124            exit(0); 
     125          } 
     126          break; 
     127        } 
     128        else { 
     129          noitL(noit_error, "Unexpected return from waitpid: %d\n", rv); 
     130          exit(-1); 
     131        } 
     132        /* Now check out timeout */ 
     133        if((ltt = last_tick_time()) > CHILD_WATCHDOG_TIMEOUT) { 
     134          noitL(noit_error, 
     135                "Watchdog timeout (%lu s)... terminating child\n", 
     136                ltt); 
     137          kill(child_pid, SIGKILL); 
     138        } 
     139      } 
     140      noitL(noit_error, "noitd child died [%d/%d], restarting.\n", exit_val, sig); 
     141    } 
     142  } 
     143} 
     144 
     145static int watchdog_tick(eventer_t e, int mask, void *unused, struct timeval *now) { 
     146  it_ticks(); 
     147  return 0; 
     148} 
     149static int child_main() { 
     150  eventer_t e; 
     151 
     152  /* Load our config... 
     153   * to ensure it is current w.r.t. to this child starting */ 
     154  if(noit_conf_load(config_file) == -1) { 
     155    noitL(noit_error, "Cannot load config: '%s'\n", config_file); 
     156  } 
     157 
     158  /* initialize the eventer */ 
     159  if(eventer_init() == -1) { 
     160    noitL(noit_stderr, "Cannot initialize eventer\n"); 
     161    exit(-1); 
     162  } 
     163 
     164  /* Setup our hearbeat */ 
     165  e = eventer_alloc(); 
     166  e->mask = EVENTER_RECURRENT; 
     167  e->callback = watchdog_tick; 
     168  eventer_add_recurrent(e); 
     169 
     170  /* Initialize all of our listeners */ 
     171  noit_console_init(); 
     172  noit_jlog_listener_init(); 
     173 
     174  noit_module_init(); 
     175  noit_filters_init(); 
     176  noit_poller_init(); 
     177  noit_listener_init(APPNAME); 
     178 
     179  /* Write our log out, and setup a watchdog to write it out on change. */ 
     180  noit_conf_write_log(NULL); 
     181  noit_conf_coalesce_changes(10); /* 10 seconds of no changes before we write */ 
     182  noit_conf_watch_and_journal_watchdog(noit_conf_write_log, NULL); 
     183 
     184  eventer_loop(); 
     185  return 0; 
     186} 
     187 
    62188int main(int argc, char **argv) { 
    63189  char conf_str[1024]; 
     
    97223    exit(-1); 
    98224  } 
    99   if(eventer_init() == -1) { 
    100     noitL(noit_stderr, "Cannot init eventer %s\n", conf_str); 
    101     exit(-1); 
    102   } 
    103   /* Initialize all of our listeners */ 
    104   noit_console_init(); 
    105   noit_jlog_listener_init(); 
    106  
    107   noit_module_init(); 
    108   noit_filters_init(); 
    109   noit_poller_init(); 
    110   noit_listener_init(APPNAME); 
    111  
    112   /* Write our log out, and setup a watchdog to write it out on change. */ 
    113   noit_conf_write_log(NULL); 
    114   noit_conf_coalesce_changes(10); /* 10 seconds of no changes before we write */ 
    115   noit_conf_watch_and_journal_watchdog(noit_conf_write_log, NULL); 
    116  
    117   eventer_loop(); 
    118   return 0; 
    119 
     225 
     226  return watch_over_child(child_main); 
     227