aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/comp.c32
-rw-r--r--src/pies.c2
-rw-r--r--src/pies.h2
-rw-r--r--src/prog.h5
-rw-r--r--src/progman.c95
-rw-r--r--src/sysvinit.c42
6 files changed, 102 insertions, 76 deletions
diff --git a/src/comp.c b/src/comp.c
index 6a0e4ba..b340abe 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -355,37 +355,21 @@ component_config_rollback (void)
static int
prog_is_leftover (struct prog *prog)
{
return IS_COMPONENT (prog) && !component_is_active (prog->v.p.comp);
}
-/* If PROG is a leftover, gracefully stop it and mark as disabled */
+/* If PROG is a leftover, mark it for termination */
static int
-cb_terminate_prog (struct prog *prog, void *data)
+mark_prog (struct prog *prog, void *data)
{
if (prog_is_leftover (prog))
- progman_stop_component (&prog);
+ prog->v.p.stop = 1;
return 0;
}
-/* If PROG is a leftover, slay it with SIGKILL */
-static int
-cb_kill_prog (struct prog *prog, void *data)
-{
- if (prog_is_leftover (prog))
- prog_stop (prog, SIGKILL);
- return 0;
-}
-
-static int
-list_is_empty (void *p)
-{
- struct complist *list = p;
- return list->head == NULL;
-}
-
static int
list_str_cmp (const void *a, const void *b)
{
return safe_strcmp (a, b);
}
@@ -501,22 +485,18 @@ component_config_commit (void)
comp = match;
}
comp_array[i] = comp;
comp->arridx = i;
}
- /* Terminate orphaned progs */
+ /* Mark orphaned progs for termination */
list = &comp_list[prev];
if (list->head)
{
- progman_foreach (cb_terminate_prog, NULL);
- if (progman_wait_until (list_is_empty, list))
- {
- progman_foreach (cb_kill_prog, NULL);
- progman_wait_until (list_is_empty, list);
- }
+ progman_foreach (mark_prog, NULL);
+ pies_schedule_children (PIES_CHLD_GC);
}
/* Build dependency map */
component_build_depmap ();
/* Register new progs */
diff --git a/src/pies.c b/src/pies.c
index 046f681..cb4d2f5 100644
--- a/src/pies.c
+++ b/src/pies.c
@@ -2218,12 +2218,14 @@ main (int argc, char **argv)
sysvinit_power ();
pies_schedule_children (PIES_CHLD_WAKEUP);
action = ACTION_CONT;
}
if (action == ACTION_CONT)
{
+ if (children_op & PIES_CHLD_GC)
+ progman_gc ();
if (children_op & PIES_CHLD_CLEANUP)
progman_cleanup (0);
if (children_op & PIES_CHLD_WAKEUP)
progman_wake_sleeping (1);
children_op = PIES_CHLD_NONE;
}
diff --git a/src/pies.h b/src/pies.h
index 9a3dfca..b61e11b 100644
--- a/src/pies.h
+++ b/src/pies.h
@@ -315,25 +315,25 @@ void free_redirector (struct redirector *rp);
void pies_schedule_action (int act);
void free_action (struct action *act);
#define PIES_CHLD_NONE 0
#define PIES_CHLD_CLEANUP 0x01
#define PIES_CHLD_WAKEUP 0x02
+#define PIES_CHLD_GC 0x04
void pies_schedule_children (int op);
void register_prog (struct component *comp);
int progman_waiting_p (void);
void progman_start (void);
void progman_wake_sleeping (int);
void progman_stop (void);
void progman_cleanup (int expect_term);
void progman_filter (int (*filter) (struct component *, void *data),
void *data);
int progman_wait_until (int (*cond) (void *), void *data);
-void progman_stop_tag (const char *name);
int progman_accept (int socket, void *data);
void progman_create_sockets (void);
struct component *progman_lookup_component (const char *tag);
struct component *progman_lookup_tcpmux (const char *service,
const char *master);
diff --git a/src/prog.h b/src/prog.h
index 316a229..4e86596 100644
--- a/src/prog.h
+++ b/src/prog.h
@@ -48,14 +48,15 @@ struct prog
int facility;
union
{
struct
{
struct component *comp;
- int wait :1;
- int active :1;
+ int active :1; /* The prog is active */
+ int wait :1; /* Wait for this prog to terminate */
+ int stop :1; /* Stop this prog */
int socket;
struct prog *redir[2]; /* Pointers to redirectors */
time_t timestamp; /* Time of last startup */
size_t failcount; /* Number of failed starts since timestamp */
enum prog_status status; /* Current component status */
/* If status == status_listener: */
diff --git a/src/progman.c b/src/progman.c
index da5a970..52c875f 100644
--- a/src/progman.c
+++ b/src/progman.c
@@ -949,13 +949,12 @@ check_connection_rate (struct prog *prog)
prog_tag (prog), SLEEPTIME / 60);
return 1;
}
return 0;
}
-
static int
prog_open_socket (struct prog *prog)
{
prog->v.p.socket = create_socket (prog->v.p.comp->socket_url,
prog->v.p.comp->socket_type,
prog->v.p.comp->privs.user,
@@ -1470,13 +1469,12 @@ prog_create_socket (struct prog *prog, void *data)
void
progman_create_sockets ()
{
progman_foreach (prog_create_socket, NULL);
}
-
void
progman_recompute_alarm ()
{
struct prog *prog;
time_t now = time (NULL);
time_t alarm_time = 0, x;
@@ -1505,15 +1503,13 @@ progman_recompute_alarm ()
}
}
debug (2, ("alarm=%lu", (unsigned long)alarm_time));
if (alarm_time)
alarm (alarm_time);
}
-
-
void
progman_start ()
{
struct prog *prog;
if (progman_waiting_p ())
@@ -2312,12 +2308,13 @@ progman_cleanup (int expect_term)
}
prog->pid = 0;
switch (prog->type)
{
case TYPE_COMPONENT:
print_status (prog_tag (prog), pid, status, expect_term);
+ prog->v.p.stop = 0;
if (prog->v.p.comp->mode == pies_comp_inetd)
{
struct prog *listener = prog->v.p.listener;
listener->v.p.num_instances--;
if (prog->v.p.cclass)
@@ -2415,37 +2412,44 @@ progman_stop_component (struct prog **progptr)
break;
case status_listener:
prog_deactivate_listener (prog);
/* fall through */
case status_stopped:
+ prog->v.p.stop = 0;
if (!component_is_active (prog->v.p.comp))
destroy_prog (progptr);
break;
case status_sleeping:
if (!component_is_active (prog->v.p.comp))
destroy_prog (progptr);
+ else if (prog->v.p.stop)
+ prog->v.p.stop = 0;
else
{
logmsg (LOG_INFO, _("waking up component `%s'"), prog_tag (prog));
prog->v.p.failcount = 0;
}
break;
+
+ case status_stopping:
+ break;
- default:
+ case status_finished:
+ prog->v.p.stop = 0;
if (!component_is_active (prog->v.p.comp))
destroy_prog (progptr);
else
logmsg (LOG_INFO,
_("stopping component `%s': component not started"),
prog_tag (prog));
}
}
}
-
+
void
prog_deactivate_listener (struct prog *prog)
{
logmsg (LOG_INFO, _("deactivating listener `%s'"), prog_tag (prog));
if (prog->v.p.socket != -1)
{
@@ -2475,15 +2479,86 @@ prog_activate_listener (struct prog *prog)
}
else
prog->v.p.socket = fd;
}
return 0;
}
+
+/* Starting at PROG, find first program component marked for termination. */
+static struct prog *
+prog_to_stop (struct prog *prog)
+{
+ for (; prog; prog = prog->next)
+ if (IS_COMPONENT (prog) && prog->v.p.stop)
+ break;
+ return prog;
+}
+
+#define DIAG_CON \
+ (init_process ? (DIAG_TO_STDERR|DIAG_REOPEN_LOG) : diag_output)
+/* Stop all program components marked for termination. Wait at most
+ 2*shutdown_timeout seconds. */
void
-progman_stop_tag (const char *name)
+progman_gc ()
{
- struct prog *prog = progman_locate (name);
- progman_stop_component (&prog);
-}
+ time_t start;
+ struct prog *prog, *next;
+
+ /* Find first marked prog */
+ prog = prog_to_stop (proghead);
+ if (!prog)
+ return;
+
+ /* First round: */
+ /* Gracefully stop it and all marked programs that follow */
+ diagmsg (DIAG_CON, LOG_INFO, "Sending processes the TERM signal");
+ start = time (NULL);
+ do
+ {
+ next = prog->next;
+ progman_stop_component (&prog);
+ }
+ while ((prog = prog_to_stop (next)));
+
+ /* Wait for them to terminate */
+ while (1)
+ {
+ progman_cleanup (1);
+ prog = prog_to_stop (proghead);
+ if (!prog)
+ return;
+ if (time (NULL) - start < shutdown_timeout)
+ sleep (1);
+ else
+ break;
+ }
+
+ /* Second round: */
+ /* Kill the remaining programs with SIGKILL */
+ diagmsg (DIAG_CON, LOG_INFO, "Sending processes the KILL signal");
+ start = time (NULL);
+ do
+ {
+ next = prog->next;
+ prog_stop (prog, SIGKILL);
+ }
+ while ((prog = prog_to_stop (next)));
+ /* Wait for them to terminate */
+ while (1)
+ {
+ progman_cleanup (1);
+ prog = prog_to_stop (proghead);
+ if (!prog)
+ return;
+ if (time (NULL) - start < shutdown_timeout)
+ sleep (1);
+ else
+ break;
+ }
+
+ /* FIXME: Report remaining programs */
+
+}
+
/* EOF */
diff --git a/src/sysvinit.c b/src/sysvinit.c
index 6276228..41d5b9d 100644
--- a/src/sysvinit.c
+++ b/src/sysvinit.c
@@ -59,13 +59,12 @@ int runlevel = 0;
int prevlevel = 'N';
int initdefault; /* Default runlevel */
int dfl_level;
int emergency_shell;
-#define DIAG_CON (DIAG_TO_STDERR|DIAG_REOPEN_LOG)
int
console_open (int mode)
{
int i, fd;
@@ -279,17 +278,20 @@ runlevel_setup_prog (struct prog *prog, void *data)
{
if (IS_COMPONENT (prog)
&& !(prog->v.p.comp->flags & CF_DISABLED)
&& is_sysvinit (prog->v.p.comp))
{
int rc = enablecomp (prog, data);
- if (rc < 0)
+ if (rc < 0 || prog->v.p.active == rc)
return 0;
prog->v.p.active = rc;
if (rc)
prog->v.p.wait = is_comp_wait (prog->v.p.comp);
+ else if (prog->v.p.status != status_stopped
+ && prog->v.p.status != status_finished)
+ prog->v.p.stop = 1;
debug (2, ("%s: %s%s", prog_tag (prog),
prog->v.p.active ?
"enabled" : "disabled",
prog->v.p.active && prog->v.p.wait ? " (wait)" : ""));
}
return 0;
@@ -298,12 +300,13 @@ runlevel_setup_prog (struct prog *prog, void *data)
void
sysvinit_runlevel_setup (int mask)
{
struct enstate s;
s.mask = mask;
progman_foreach (runlevel_setup_prog, &s);
+ pies_schedule_children (PIES_CHLD_GC);
}
static int
demand_prog (struct prog *prog, void *data)
{
int *rl = data;
@@ -760,32 +763,12 @@ sysvinit_begin ()
#define IS_RUNNING_DISABLED_PROG(prog) \
(IS_COMPONENT (prog) \
&& prog->v.p.status == status_running \
&& !prog->v.p.active)
-static int
-cond_running_disabled (struct prog *prog, void *data)
-{
- return IS_RUNNING_DISABLED_PROG (prog);
-}
-
-static int
-no_disabled_running (void *data)
-{
- return !progman_foreach (cond_running_disabled, NULL);
-}
-
-static int
-terminate_disabled (struct prog *prog, void *data)
-{
- if (IS_RUNNING_DISABLED_PROG (prog))
- prog_stop (prog, *(int*)data);
- return 0;
-}
-
int
inittrans ()
{
int n;
int newlevel = 0;
enum boot_state newstate;
@@ -841,29 +824,14 @@ inittrans ()
runlevel = newlevel;
trans = 1;
}
if (trans)
{
- int sig;
-
envsetup ();
sysvinit_runlevel_setup (PIES_COMP_DEFAULT);
-
- /* Stop disabled programs */
- sig = SIGTERM;
- diagmsg (DIAG_CON, LOG_INFO, "Sending processes the TERM signal");
- progman_foreach (terminate_disabled, &sig);
- if (progman_wait_until (no_disabled_running, NULL))
- {
- sig = SIGKILL;
- diagmsg (DIAG_CON, LOG_INFO, "Sending processes the KILL signal");
- progman_foreach (terminate_disabled, &sig);
- progman_wait_until (no_disabled_running, NULL);
- }
-
pies_schedule_children (PIES_CHLD_WAKEUP);
}
return trans;
}
/* Return true if the progman should wait for the component to

Return to:

Send suggestions and report system problems to the System administrator.