Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 83ada447 authored by Colin Cross's avatar Colin Cross Committed by Gerrit Code Review
Browse files

Merge changes Ib54f39fd,I7e36edd8

* changes:
  init: Retain traditional restart behavior for critical and oneshot services.
  init: Safely restart services to avoid race conditions.
parents e755dfd4 b54f39fd
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -590,8 +590,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;
}
+29 −9
Original line number Diff line number Diff line
@@ -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);
    }
+2 −0
Original line number Diff line number Diff line
@@ -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);

+6 −4
Original line number Diff line number Diff line
@@ -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. */