am 39021a48: am 83ada447: Merge changes Ib54f39fd,I7e36edd8
* commit '39021a48a0e0687c654423acd5a4c99a1d79440d': init: Retain traditional restart behavior for critical and oneshot services. init: Safely restart services to avoid race conditions.
This commit is contained in:
commit
372d668a27
|
@ -593,8 +593,7 @@ int do_restart(int nargs, char **args)
|
|||
struct service *svc;
|
||||
svc = service_find_by_name(args[1]);
|
||||
if (svc) {
|
||||
service_stop(svc);
|
||||
service_start(svc, NULL);
|
||||
service_restart(svc);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
38
init/init.c
38
init/init.c
|
@ -164,7 +164,7 @@ void service_start(struct service *svc, const char *dynamic_args)
|
|||
* state and immediately takes it out of the restarting
|
||||
* state if it was in there
|
||||
*/
|
||||
svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET));
|
||||
svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART));
|
||||
svc->time_started = 0;
|
||||
|
||||
/* running processes require no additional work -- if
|
||||
|
@ -359,15 +359,14 @@ void service_start(struct service *svc, const char *dynamic_args)
|
|||
notify_service_state(svc->name, "running");
|
||||
}
|
||||
|
||||
/* The how field should be either SVC_DISABLED or SVC_RESET */
|
||||
/* The how field should be either SVC_DISABLED, SVC_RESET, or SVC_RESTART */
|
||||
static void service_stop_or_reset(struct service *svc, int how)
|
||||
{
|
||||
/* we are no longer running, nor should we
|
||||
* attempt to restart
|
||||
*/
|
||||
svc->flags &= (~(SVC_RUNNING|SVC_RESTARTING));
|
||||
/* The service is still SVC_RUNNING until its process exits, but if it has
|
||||
* already exited it shoudn't attempt a restart yet. */
|
||||
svc->flags &= (~SVC_RESTARTING);
|
||||
|
||||
if ((how != SVC_DISABLED) && (how != SVC_RESET)) {
|
||||
if ((how != SVC_DISABLED) && (how != SVC_RESET) && (how != SVC_RESTART)) {
|
||||
/* Hrm, an illegal flag. Default to SVC_DISABLED */
|
||||
how = SVC_DISABLED;
|
||||
}
|
||||
|
@ -399,6 +398,17 @@ void service_stop(struct service *svc)
|
|||
service_stop_or_reset(svc, SVC_DISABLED);
|
||||
}
|
||||
|
||||
void service_restart(struct service *svc)
|
||||
{
|
||||
if (svc->flags & SVC_RUNNING) {
|
||||
/* Stop, wait, then start the service. */
|
||||
service_stop_or_reset(svc, SVC_RESTART);
|
||||
} else if (!(svc->flags & SVC_RESTARTING)) {
|
||||
/* Just start the service since it's not running. */
|
||||
service_start(svc, NULL);
|
||||
} /* else: Service is restarting anyways. */
|
||||
}
|
||||
|
||||
void property_changed(const char *name, const char *value)
|
||||
{
|
||||
if (property_triggers_enabled)
|
||||
|
@ -467,6 +477,17 @@ static void msg_stop(const char *name)
|
|||
}
|
||||
}
|
||||
|
||||
static void msg_restart(const char *name)
|
||||
{
|
||||
struct service *svc = service_find_by_name(name);
|
||||
|
||||
if (svc) {
|
||||
service_restart(svc);
|
||||
} else {
|
||||
ERROR("no such service '%s'\n", name);
|
||||
}
|
||||
}
|
||||
|
||||
void handle_control_message(const char *msg, const char *arg)
|
||||
{
|
||||
if (!strcmp(msg,"start")) {
|
||||
|
@ -474,8 +495,7 @@ void handle_control_message(const char *msg, const char *arg)
|
|||
} else if (!strcmp(msg,"stop")) {
|
||||
msg_stop(arg);
|
||||
} else if (!strcmp(msg,"restart")) {
|
||||
msg_stop(arg);
|
||||
msg_start(arg);
|
||||
msg_restart(arg);
|
||||
} else {
|
||||
ERROR("unknown control msg '%s'\n", msg);
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@ struct svcenvinfo {
|
|||
#define SVC_RESET 0x40 /* Use when stopping a process, but not disabling
|
||||
so it can be restarted with its class */
|
||||
#define SVC_RC_DISABLED 0x80 /* Remember if the disabled flag was set in the rc script */
|
||||
#define SVC_RESTART 0x100 /* Use to safely restart (stop, wait, start) a service */
|
||||
|
||||
#define NR_SVC_SUPP_GIDS 12 /* twelve supplementary groups */
|
||||
|
||||
|
@ -127,6 +128,7 @@ void service_for_each_flags(unsigned matchflags,
|
|||
void (*func)(struct service *svc));
|
||||
void service_stop(struct service *svc);
|
||||
void service_reset(struct service *svc);
|
||||
void service_restart(struct service *svc);
|
||||
void service_start(struct service *svc, const char *dynamic_args);
|
||||
void property_changed(const char *name, const char *value);
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ static int wait_for_one_process(int block)
|
|||
|
||||
NOTICE("process '%s', pid %d exited\n", svc->name, pid);
|
||||
|
||||
if (!(svc->flags & SVC_ONESHOT)) {
|
||||
if (!(svc->flags & SVC_ONESHOT) || (svc->flags & SVC_RESTART)) {
|
||||
kill(-pid, SIGKILL);
|
||||
NOTICE("process '%s' killing any children in process group\n", svc->name);
|
||||
}
|
||||
|
@ -78,8 +78,9 @@ static int wait_for_one_process(int block)
|
|||
svc->pid = 0;
|
||||
svc->flags &= (~SVC_RUNNING);
|
||||
|
||||
/* oneshot processes go into the disabled state on exit */
|
||||
if (svc->flags & SVC_ONESHOT) {
|
||||
/* oneshot processes go into the disabled state on exit,
|
||||
* except when manually restarted. */
|
||||
if ((svc->flags & SVC_ONESHOT) && !(svc->flags & SVC_RESTART)) {
|
||||
svc->flags |= SVC_DISABLED;
|
||||
}
|
||||
|
||||
|
@ -90,7 +91,7 @@ static int wait_for_one_process(int block)
|
|||
}
|
||||
|
||||
now = gettime();
|
||||
if (svc->flags & SVC_CRITICAL) {
|
||||
if ((svc->flags & SVC_CRITICAL) && !(svc->flags & SVC_RESTART)) {
|
||||
if (svc->time_crashed + CRITICAL_CRASH_WINDOW >= now) {
|
||||
if (++svc->nr_crashed > CRITICAL_CRASH_THRESHOLD) {
|
||||
ERROR("critical process '%s' exited %d times in %d minutes; "
|
||||
|
@ -105,6 +106,7 @@ static int wait_for_one_process(int block)
|
|||
}
|
||||
}
|
||||
|
||||
svc->flags &= (~SVC_RESTART);
|
||||
svc->flags |= SVC_RESTARTING;
|
||||
|
||||
/* Execute all onrestart commands for this service. */
|
||||
|
|
Loading…
Reference in New Issue