diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2008-11-21 16:26:19 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2008-11-21 16:26:19 +0000 |
commit | f4625d1d73214d46e3594b28247ea7d26411aca7 (patch) | |
tree | 56923058a8b9d7d313dea27a83d9b965508d08d9 | |
parent | ab854f93828c3c2f9797e3d458ec7a6f2b0961ec (diff) | |
download | pies-f4625d1d73214d46e3594b28247ea7d26411aca7.tar.gz pies-f4625d1d73214d46e3594b28247ea7d26411aca7.tar.bz2 |
Pies: ensure all prereqs are started in right order before starting a dependency.
* pies/pies.c (component_cfg_param): New statement settle-timeout.
* pies/progman.c (recompute_alarm): New static;
(prog_start): Start the component only if all of its prerequisites
are running.
(progman_recompute_alarm): New function.
(progman_start): Reset recompute_alarm to 0.
(check_stopping): New function.
(progman_wake_sleeping): Handle also status_stopping and
status_enabled. Recompute alarm before leaving.
(prog_start_prerequisites): Return 0 or 1 depending on whether all
prerequisites have been started.
(prog_stop): Raise recompute_alarm for stopping components.
(progman_cleanup): Force status_enabled before attepmting to
start a component.
(progman_cleanup): Add a \n after debugging message.
Run progman_wake_sleeping unlsess expect_term is set.
* pies/meta1gram.y (translate_node_list): Force settle-timeout =
1.
* pies/pies.h (struct component.settle_timeout): New member.
-rw-r--r-- | pies/meta1gram.y | 3 | ||||
-rw-r--r-- | pies/pies.c | 3 | ||||
-rw-r--r-- | pies/pies.h | 35 | ||||
-rw-r--r-- | pies/progman.c | 208 |
4 files changed, 186 insertions, 63 deletions
diff --git a/pies/meta1gram.y b/pies/meta1gram.y index 334cb61..7ab93a7 100644 --- a/pies/meta1gram.y +++ b/pies/meta1gram.y @@ -415,6 +415,9 @@ translate_node_list (mu_cfg_node_t *src, const char *name) tail->next = node; tail = node; + node = create_string_node ("settle-timeout", "1", locus); + tail->next = node; + tail = node; } return head; } diff --git a/pies/pies.c b/pies/pies.c index f39f1d4..836ea9c 100644 --- a/pies/pies.c +++ b/pies/pies.c @@ -598,6 +598,9 @@ struct mu_cfg_param component_cfg_param[] = { { "disable", mu_cfg_bool, NULL, mu_offsetof (struct component, disabled), NULL, N_("Disable this entry.") }, + { "settle-timeout", mu_cfg_uint, NULL, + mu_offsetof (struct component, settle_timeout), NULL, + N_("Time to wait before starting this component.") }, { "precious", mu_cfg_bool, NULL, mu_offsetof (struct component, precious), NULL, N_("Mark this entry as precious.") }, diff --git a/pies/pies.h b/pies/pies.h index 1b6f07e..2591ea0 100644 --- a/pies/pies.h +++ b/pies/pies.h @@ -111,22 +111,25 @@ enum pies_comp_mode struct component { enum pies_comp_mode mode; - char *tag; /* Entry tag (for diagnostics purposes) */ - char *program; /* Program name */ - char **argv; /* Program command line */ - char **env; /* Program environment */ - char *dir; /* Working directory */ - mu_list_t prereq; /* Prerequisites */ - mu_list_t depend; /* Dependency targets */ - /* FIXME: disabled and precios can be encoded as bits in mode */ - int disabled; /* The componenet is disabled */ - int precious; /* The component is precious (cannot be disabled) */ - char *rmfile; /* Try to remove this file before starting */ - struct mf_privs privs; /* UID/GIDS+groups to run under */ - mode_t umask; /* Umask to install before starting */ - limits_record_t limits;/* System limits */ - mu_url_t socket_url; /* Socket to listen on (if mode != pies_comp_exec) */ - char *pass_fd_socket; /* Socket to pass fd on + char *tag; /* Entry tag (for diagnostics purposes) */ + char *program; /* Program name */ + char **argv; /* Program command line */ + char **env; /* Program environment */ + char *dir; /* Working directory */ + mu_list_t prereq; /* Prerequisites */ + mu_list_t depend; /* Dependency targets */ + unsigned settle_timeout; /* Time needed for started prerequisites to + settle */ + /* FIXME: disabled and precious can be encoded as bits in mode */ + int disabled; /* The componenet is disabled */ + int precious; /* The component is precious (cannot be disabled) */ + char *rmfile; /* Try to remove this file before starting */ + struct mf_privs privs; /* UID/GIDS+groups to run under */ + mode_t umask; /* Umask to install before starting */ + limits_record_t limits; /* System limits */ + mu_url_t socket_url; /* Socket to listen on + (if mode != pies_comp_exec) */ + char *pass_fd_socket; /* Socket to pass fd on (if mode == pies_comp_pass_fd) */ mu_acl_t acl; /* Retranslators: */ diff --git a/pies/progman.c b/pies/progman.c index 29db153..9a5b0c5 100644 --- a/pies/progman.c +++ b/pies/progman.c @@ -64,6 +64,7 @@ struct prog static int numprog; static struct prog *proghead, *progtail; static pies_depmap_t depmap; +static int recompute_alarm; static struct prog * prog_lookup_by_pid (pid_t pid) @@ -118,7 +119,7 @@ prog_lookup_by_idx (unsigned idx) } static void prog_stop (struct prog *prog, int sig); -void prog_start_prerequisites (struct prog *prog); +static int prog_start_prerequisites (struct prog *prog); void link_prog (struct prog *pp, int prepend) @@ -573,6 +574,38 @@ prog_start (struct prog *prog) if (prog->pid > 0 || !IS_PROG (prog)) return; + + /* This call returns 1 in two cases: Either prog is marked as disabled, + in which case there's nothing more to do, or one or more of its + prerequisites are in status_stopping. In the latter case either the + components in question will exit or a SIGALRM will get delivered. In + both cases, it will cause further processing of `prog'. */ + if (prog_start_prerequisites (prog)) + return; + + time (&now); + + if (prog->v.p.timestamp + TESTTIME > now) + prog->v.p.count++; + else + { + prog->v.p.count = 0; + prog->v.p.timestamp = now; + } + + if (prog->v.p.count > MAXSPAWN) + { + mu_error (ngettext ( + "%s is respawning too fast, disabled for %d minute", + "%s is respawning too fast, disabled for %d minutes", + SLEEPTIME / 60), + prog->tag, SLEEPTIME / 60); + prog->v.p.timestamp = now; + prog->v.p.status = status_sleeping; + recompute_alarm = 1; + return; + } + switch (prog->v.p.comp->mode) { case pies_comp_exec: @@ -602,6 +635,7 @@ prog_start (struct prog *prog) { mu_error ("listen: %s", mu_strerror (errno)); close (prog->v.p.socket); + prog->v.p.socket = -1; prog->v.p.status = status_disabled; return; } @@ -613,38 +647,6 @@ prog_start (struct prog *prog) return; } - time (&now); - - if (prog->v.p.timestamp + TESTTIME > now) - prog->v.p.count++; - else - { - prog->v.p.count = 0; - prog->v.p.timestamp = now; - } - - if (prog->v.p.count > MAXSPAWN) - { - int old_alarm; - - mu_error (ngettext ( - "%s is respawning too fast, disabled for %d minute", - "%s is respawning too fast, disabled for %d minutes", - SLEEPTIME / 60), - prog->tag, SLEEPTIME / 60); - prog->v.p.timestamp = now; - prog->v.p.status = status_sleeping; - - old_alarm = alarm (0); - if (old_alarm > SLEEPTIME || old_alarm <= 0) - old_alarm = SLEEPTIME; - alarm (old_alarm); - return; - } - - prog_start_prerequisites (prog); - if (prog->v.p.status == status_disabled) - return; /* FIXME: other statuses */ MU_DEBUG1 (pies_debug, MU_DEBUG_TRACE1, _("starting %s\n"), prog->tag); if (prog->v.p.comp->rmfile) @@ -721,6 +723,7 @@ prog_start (struct prog *prog) dup2 (prog->v.p.socket, 0); dup2 (prog->v.p.socket, 1); close (prog->v.p.socket); + prog->v.p.socket = -1; break; } @@ -1058,10 +1061,49 @@ progman_create_sockets () void +progman_recompute_alarm () +{ + struct prog *prog; + time_t now = time (NULL); + time_t alarm_time = 0, x; + + recompute_alarm = 0; + MU_DEBUG (pies_debug, MU_DEBUG_TRACE2, "Recomputing alarm settings\n"); + for (prog = proghead; prog; prog = prog->next) + if (IS_PROG (prog)) + { + switch (prog->v.p.status) + { + case status_sleeping: + x = SLEEPTIME - (now - prog->v.p.timestamp); + if (alarm_time == 0 || x < alarm_time) + alarm_time = x; + break; + + case status_stopping: + x = shutdown_timeout - (now - prog->v.p.timestamp); + if (alarm_time == 0 || x < alarm_time) + alarm_time = x; + break; + + default: + break; + } + } + MU_DEBUG1 (pies_debug, MU_DEBUG_TRACE2, "alarm=%lu\n", + (unsigned long)alarm_time); + if (alarm_time) + alarm (alarm_time); +} + + + +void progman_start () { struct prog *prog; + recompute_alarm = 0; MU_DEBUG (pies_debug, MU_DEBUG_TRACE1, "Starting components\n"); for (prog = proghead; prog; prog = prog->next) if (IS_PROG (prog) @@ -1070,30 +1112,74 @@ progman_start () prog_start (prog); } +static void +check_stopping (struct prog *prog, time_t now) +{ + if (now - prog->v.p.timestamp >= shutdown_timeout) + { + if (prog->pid == 0) + mu_error (_("INTERNAL ERROR: attempting to kill unexisting process %s"), + prog->tag); + else + kill (prog->pid, SIGKILL); + } + else + recompute_alarm = 1; +} + void progman_wake_sleeping () { struct prog *prog; + time_t now = time (NULL); + + MU_DEBUG (pies_debug, MU_DEBUG_TRACE1, + "Managing sleeping/stopping components\n"); for (prog = proghead; prog; prog = prog->next) - if (IS_PROG (prog) && prog->v.p.status == status_sleeping) + if (IS_PROG (prog)) { - prog->v.p.status = status_enabled; - prog->v.p.count = 0; - prog->v.p.timestamp = 0; - prog_start (prog); + switch (prog->v.p.status) + { + case status_sleeping: + if (now - prog->v.p.timestamp >= SLEEPTIME) + { + prog->v.p.status = status_enabled; + prog->v.p.count = 0; + prog->v.p.timestamp = 0; + prog_start (prog); + } + break; + + case status_stopping: + check_stopping (prog, now); + break; + + case status_enabled: + if (prog->pid == 0) + prog_start (prog); + break; + + default: + break; + } } + if (recompute_alarm) + progman_recompute_alarm (); } -void +static int prog_start_prerequisites (struct prog *prog) { int i; - + int ret; + unsigned settle_timeout = 0; + if (!prog->prereq) - return; + return 0; /* Ok to startup */ MU_DEBUG1 (pies_debug, MU_DEBUG_TRACE1, "Starting prerequisites of %s\n", prog->tag); + ret = 0; for (i = 0; prog->prereq[i]; i++) { struct prog *dp = prog_lookup_by_tag (prog->prereq[i]); @@ -1103,17 +1189,36 @@ prog_start_prerequisites (struct prog *prog) continue; switch (dp->v.p.status) { + case status_enabled: + if (prog->pid != 0) + continue; + break; + case status_disabled: prog->v.p.status = status_disabled; - return; + return 1; + case status_listener: - return; - default: - /* FIXME: other states */ + continue; + + case status_sleeping: + /* FIXME: What to do in this case? */ break; + + case status_stopping: + check_stopping (dp, time (NULL)); + ret = 1; + continue; } prog_start (prog_lookup_by_tag (prog->prereq[i])); + if (!(dp->v.p.status == status_enabled && dp->pid)) + ret = 1; + else + settle_timeout = prog->v.p.comp->settle_timeout; } + if (ret == 0 && settle_timeout) + sleep (settle_timeout); + return ret; } void @@ -1160,7 +1265,11 @@ prog_stop (struct prog *prog, int sig) if (prog->type == TYPE_COMPONENT) { if (prog->v.p.status == status_enabled) - prog->v.p.status = status_stopping; + { + prog->v.p.status = status_stopping; + prog->v.p.timestamp = time (NULL); + recompute_alarm = 1; + } } MU_DEBUG2 (pies_debug, MU_DEBUG_TRACE1, "Stopping %s (%lu)\n", @@ -1378,6 +1487,7 @@ progman_cleanup (int expect_term) } else { + prog->v.p.status = status_enabled; prog_stop_dependents (prog); if (!expect_term) { @@ -1415,10 +1525,14 @@ progman_cleanup (int expect_term) { /* It was a retranslator of an already finished inetd process. */ MU_DEBUG1 (pies_debug, MU_DEBUG_TRACE1, - _("removing inetd retranslator %s"), prog->tag); + _("removing inetd retranslator %s\n"), prog->tag); destroy_prog (&prog); } } + + if (!expect_term) + /* This will also recompute alarm settings, if necessary */ + progman_wake_sleeping (); } void |