diff options
author | Colin Cross <ccross@android.com> | 2013-06-24 15:27:43 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2013-06-24 15:27:43 -0700 |
commit | 372d668a279934ff3b2ec2f07a76fe2f351789d5 (patch) | |
tree | 333e0436a0d6d200e7617694f7451e1c93bb40b8 | |
parent | 9270f12529fdcadaacd9d2bce3ceeeb07d037aa8 (diff) | |
parent | 39021a48a0e0687c654423acd5a4c99a1d79440d (diff) | |
download | system_core-372d668a279934ff3b2ec2f07a76fe2f351789d5.zip system_core-372d668a279934ff3b2ec2f07a76fe2f351789d5.tar.gz system_core-372d668a279934ff3b2ec2f07a76fe2f351789d5.tar.bz2 |
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.
-rw-r--r-- | init/builtins.c | 3 | ||||
-rwxr-xr-x | init/init.c | 38 | ||||
-rw-r--r-- | init/init.h | 2 | ||||
-rw-r--r-- | init/signal_handler.c | 10 |
4 files changed, 38 insertions, 15 deletions
diff --git a/init/builtins.c b/init/builtins.c index 0f9f131..576f0d9 100644 --- a/init/builtins.c +++ b/init/builtins.c @@ -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; } diff --git a/init/init.c b/init/init.c index fd428b0..28d2863 100755 --- a/init/init.c +++ b/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); } diff --git a/init/init.h b/init/init.h index 955e1f0..aa6a4ab 100644 --- a/init/init.h +++ b/init/init.h @@ -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); diff --git a/init/signal_handler.c b/init/signal_handler.c index abccb40..d31ad63 100644 --- a/init/signal_handler.c +++ b/init/signal_handler.c @@ -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. */ |