services: do not start services before all stopped processes has been halted

Signed-off-by: Jonas Johansson <jonas.johansson@westermo.se>
This commit is contained in:
Jonas Johansson committed 2016-05-19 14:46:59 +02:00
1 parent c1f725340d
commit c5fad8e659
3 files changed
+40 -75

No files matched your search

+8 -55
View File
@@ -42,8 +42,6 @@
#define RESPAWN_MAX 10 /* Prevent endless respawn of faulty services. */ #define RESPAWN_MAX 10 /* Prevent endless respawn of faulty services. */
static int in_teardown = 0, in_dyn_teardown = 0;
#ifndef INETD_DISABLED #ifndef INETD_DISABLED
static svc_t *find_inetd_svc (char *path, char *service, char *proto); static svc_t *find_inetd_svc (char *path, char *service, char *proto);
#endif #endif
@@ -332,19 +330,6 @@ static int service_restart(svc_t *svc)
return err; return err;
} }
/**
* service_reload_dynamic_finish - Finish dynamic service reload
*
* Second stage of dynamic reload. Called either directly from first
* stage if no services had to be stopped, or later from
* service_monitor once all stopped services have been collected.
*/
static void service_reload_dynamic_finish(void)
{
in_dyn_teardown = 0;
sm_step(&sm);
}
/** /**
* service_reload_dynamic - Called on SIGHUP, 'init q' or 'initctl reload' * service_reload_dynamic - Called on SIGHUP, 'init q' or 'initctl reload'
* *
@@ -354,24 +339,10 @@ static void service_reload_dynamic_finish(void)
*/ */
void service_reload_dynamic(void) void service_reload_dynamic(void)
{ {
in_dyn_teardown = 1;
sm_set_reload(&sm); sm_set_reload(&sm);
sm_step(&sm); sm_step(&sm);
} }
/**
* service_runlevel_finish - Finish runlevel change
*
* Second stage of runlevel change. Called either directly from first
* stage if no services had to be stopped, or later from
* service_monitor once all stopped services have been collected.
*/
static void service_runlevel_finish(void)
{
in_teardown = 0;
sm_step(&sm);
}
/** /**
* service_runlevel - Change to a new runlevel * service_runlevel - Change to a new runlevel
* @newlevel: New runlevel to activate * @newlevel: New runlevel to activate
@@ -381,7 +352,6 @@ static void service_runlevel_finish(void)
*/ */
void service_runlevel(int newlevel) void service_runlevel(int newlevel)
{ {
in_teardown = 1;
sm_set_runlevel(&sm, newlevel); sm_set_runlevel(&sm, newlevel);
sm_step(&sm); sm_step(&sm);
} }
@@ -627,29 +597,6 @@ void service_unregister(svc_t *svc)
svc_del(svc); svc_del(svc);
} }
/**
* service_teardown_finish - Complete runlevel change or dynamic reload
*
* If any runlevel change or dynamic service reload is in progress and
* all services that had to be stopped have been collected, run the
* corresponding second stage.
*/
static void service_teardown_finish(void)
{
if (!(in_teardown || in_dyn_teardown))
return;
if (!service_stop_is_done())
return;
if (in_teardown)
service_runlevel_finish();
if (in_dyn_teardown)
service_reload_dynamic_finish();
}
void service_monitor(pid_t lost) void service_monitor(pid_t lost)
{ {
svc_t *svc; svc_t *svc;
@@ -676,8 +623,7 @@ void service_monitor(pid_t lost)
svc->pid = 0; svc->pid = 0;
service_step(svc); service_step(svc);
/* Check if we're still collecting stopped dynamic services */ sm_step(&sm);
service_teardown_finish();
} }
static void svc_set_state(svc_t *svc, svc_state_t new) static void svc_set_state(svc_t *svc, svc_state_t new)
@@ -757,6 +703,10 @@ restart:
break; break;
} }
/* wait until all processes has been stopped before continuing... */
if (sm_is_in_teardown(&sm))
break;
err = service_start(svc); err = service_start(svc);
if (err) { if (err) {
(*restart_counter)++; (*restart_counter)++;
@@ -813,6 +763,9 @@ restart:
case COND_ON: case COND_ON:
if (svc_is_changed(svc)) { if (svc_is_changed(svc)) {
if (svc->sighup) { if (svc->sighup) {
/* wait until all processes has been stopped before continuing... */
if (sm_is_in_teardown(&sm))
break;
service_restart(svc); service_restart(svc);
} else { } else {
service_stop(svc); service_stop(svc);
+21 -11
View File
@@ -40,19 +40,10 @@ void sm_init(sm_t *sm)
sm->state = SM_BOOTSTRAP_STATE; sm->state = SM_BOOTSTRAP_STATE;
sm->newlevel = -1; sm->newlevel = -1;
sm->reload = 0; sm->reload = 0;
sm->in_teardown = 0;
} }
void sm_set_runlevel(sm_t *sm, int newlevel) static char *sm_status(sm_t *sm)
{
sm->newlevel = newlevel;
}
void sm_set_reload(sm_t *sm)
{
sm->reload = 1;
}
char *sm_status(sm_t *sm)
{ {
switch (sm->state) { switch (sm->state) {
case SM_BOOTSTRAP_STATE: case SM_BOOTSTRAP_STATE:
@@ -72,6 +63,21 @@ char *sm_status(sm_t *sm)
} }
} }
void sm_set_runlevel(sm_t *sm, int newlevel)
{
sm->newlevel = newlevel;
}
void sm_set_reload(sm_t *sm)
{
sm->reload = 1;
}
int sm_is_in_teardown(sm_t *sm)
{
return sm->in_teardown;
}
void sm_step(sm_t *sm) void sm_step(sm_t *sm)
{ {
sm_state_t old_state; sm_state_t old_state;
@@ -117,6 +123,7 @@ restart:
conf_reload_dynamic(); conf_reload_dynamic();
_d("Stopping services services not allowed in new runlevel ..."); _d("Stopping services services not allowed in new runlevel ...");
sm->in_teardown = 1;
service_step_all(SVC_TYPE_ANY); service_step_all(SVC_TYPE_ANY);
sm->state = SM_RUNLEVEL_WAIT_STATE; sm->state = SM_RUNLEVEL_WAIT_STATE;
@@ -133,6 +140,7 @@ restart:
plugin_run_hooks(HOOK_RUNLEVEL_CHANGE); /* Reconfigure HW/VLANs/etc here */ plugin_run_hooks(HOOK_RUNLEVEL_CHANGE); /* Reconfigure HW/VLANs/etc here */
_d("Starting services services new to this runlevel ..."); _d("Starting services services new to this runlevel ...");
sm->in_teardown = 0;
service_step_all(SVC_TYPE_ANY); service_step_all(SVC_TYPE_ANY);
/* Cleanup stale services */ /* Cleanup stale services */
@@ -168,6 +176,7 @@ restart:
/* Then, mark all affected service conditions as in-flux and /* Then, mark all affected service conditions as in-flux and
* let all affected services move to WAITING/HALTED */ * let all affected services move to WAITING/HALTED */
_d("Stopping services services not allowed after reconf ..."); _d("Stopping services services not allowed after reconf ...");
sm->in_teardown = 1;
cond_reload(); cond_reload();
service_step_all(SVC_TYPE_SERVICE | SVC_TYPE_INETD); service_step_all(SVC_TYPE_SERVICE | SVC_TYPE_INETD);
@@ -180,6 +189,7 @@ restart:
if (!service_stop_is_done()) if (!service_stop_is_done())
break; break;
sm->in_teardown = 0;
/* Cleanup stale services */ /* Cleanup stale services */
svc_clean_dynamic(service_unregister); svc_clean_dynamic(service_unregister);
+11 -9
View File
@@ -25,24 +25,26 @@
#define FINIT_SM_H_ #define FINIT_SM_H_
typedef enum { typedef enum {
SM_BOOTSTRAP_STATE = 0, SM_BOOTSTRAP_STATE = 0, /* Init state, bootstrap services */
SM_RUNNING_STATE, SM_RUNNING_STATE, /* Normal state, services running */
SM_RUNLEVEL_CHANGE_STATE, SM_RUNLEVEL_CHANGE_STATE, /* A runlevel change has occured */
SM_RUNLEVEL_WAIT_STATE, SM_RUNLEVEL_WAIT_STATE, /* Waiting for all stopped runlevel processes to be halted */
SM_RELOAD_CHANGE_STATE, SM_RELOAD_CHANGE_STATE, /* A reload event has occured */
SM_RELOAD_WAIT_STATE, SM_RELOAD_WAIT_STATE, /* Waiting for all stopped reload processes to be halted */
} sm_state_t; } sm_state_t;
typedef struct sm { typedef struct sm {
sm_state_t state; sm_state_t state; /* Running, Changed, Waiting, ... */
int newlevel; int newlevel; /* Set on runlevel change to new runlevel, -1 if not change */
int reload; int reload; /* Set on reload event, else 0 */
int in_teardown; /* Set when waiting for all processes to be halted */
} sm_t; } sm_t;
void sm_init(sm_t *sm); void sm_init(sm_t *sm);
void sm_step(sm_t *sm); void sm_step(sm_t *sm);
void sm_set_runlevel(sm_t *sm, int newlevel); void sm_set_runlevel(sm_t *sm, int newlevel);
void sm_set_reload(sm_t *sm); void sm_set_reload(sm_t *sm);
int sm_is_in_teardown(sm_t *sm);
#endif /* FINIT_SM_H_ */ #endif /* FINIT_SM_H_ */