Exemplo n.º 1
0
int scope_abandon(Scope *s) {
        assert(s);

        if (!IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED))
                return -ESTALE;

        free(s->controller);
        s->controller = NULL;

        /* The client is no longer watching the remaining processes,
         * so let's step in here, under the assumption that the
         * remaining processes will be sooner or later reassigned to
         * us as parent. */

        unit_tidy_watch_pids(UNIT(s), 0, 0);
        unit_watch_all_pids(UNIT(s));

        /* If the PID set is empty now, then let's finish this off */
        if (set_isempty(UNIT(s)->pids))
                scope_notify_cgroup_empty_event(UNIT(s));
        else
                scope_set_state(s, SCOPE_ABANDONED);

        return 0;
}
Exemplo n.º 2
0
static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
        int r;

        assert(s);

        if (f != SCOPE_SUCCESS)
                s->result = f;

        r = unit_kill_context(
                        UNIT(s),
                        &s->kill_context,
                        state != SCOPE_STOP_SIGTERM,
                        -1, -1, false);
        if (r < 0)
                goto fail;

        if (r > 0) {
                r = scope_arm_timer(s);
                if (r < 0)
                        goto fail;

                scope_set_state(s, state);
        } else
                scope_enter_dead(s, SCOPE_SUCCESS);

        return;

fail:
        log_warning_unit(UNIT(s)->id,
                         "%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));

        scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
}
Exemplo n.º 3
0
static int scope_start(Unit *u) {
        Scope *s = SCOPE(u);
        int r;

        assert(s);

        if (s->state == SCOPE_FAILED)
                return -EPERM;

        if (s->state == SCOPE_STOP_SIGTERM ||
            s->state == SCOPE_STOP_SIGKILL)
                return -EAGAIN;

        assert(s->state == SCOPE_DEAD);

        if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
                return -ENOENT;

        r = unit_realize_cgroup(u);
        if (r < 0) {
                log_error("Failed to realize cgroup: %s", strerror(-r));
                return r;
        }

        r = cg_attach_many_everywhere(u->manager->cgroup_supported, u->cgroup_path, UNIT(s)->pids);
        if (r < 0)
                return r;

        s->result = SCOPE_SUCCESS;

        scope_set_state(s, SCOPE_RUNNING);
        return 0;
}
Exemplo n.º 4
0
static int scope_start(Unit *u) {
        Scope *s = SCOPE(u);
        int r;

        assert(s);

        if (s->state == SCOPE_FAILED)
                return -EPERM;

        /* We can't fulfill this right now, please try again later */
        if (s->state == SCOPE_STOP_SIGTERM ||
            s->state == SCOPE_STOP_SIGKILL)
                return -EAGAIN;

        assert(s->state == SCOPE_DEAD);

        if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
                return -ENOENT;

        (void) unit_realize_cgroup(u);
        (void) unit_reset_cpu_usage(u);

        r = unit_attach_pids_to_cgroup(u);
        if (r < 0) {
                log_unit_warning_errno(UNIT(s), r, "Failed to add PIDs to scope's control group: %m");
                scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
                return r;
        }

        s->result = SCOPE_SUCCESS;

        scope_set_state(s, SCOPE_RUNNING);
        return 1;
}
Exemplo n.º 5
0
static void scope_enter_dead(Scope *s, ScopeResult f) {
        assert(s);

        if (f != SCOPE_SUCCESS)
                s->result = f;

        scope_set_state(s, s->result != SCOPE_SUCCESS ? SCOPE_FAILED : SCOPE_DEAD);
}
Exemplo n.º 6
0
static void scope_enter_dead(Scope *s, ScopeResult f) {
        assert(s);

        if (s->result == SCOPE_SUCCESS)
                s->result = f;

        unit_log_result(UNIT(s), s->result == SCOPE_SUCCESS, scope_result_to_string(s->result));
        scope_set_state(s, s->result != SCOPE_SUCCESS ? SCOPE_FAILED : SCOPE_DEAD);
}
Exemplo n.º 7
0
static void scope_reset_failed(Unit *u) {
        Scope *s = SCOPE(u);

        assert(s);

        if (s->state == SCOPE_FAILED)
                scope_set_state(s, SCOPE_DEAD);

        s->result = SCOPE_SUCCESS;
}
Exemplo n.º 8
0
static void scope_enter_dead(Scope *s, ScopeResult f) {
        assert(s);

        if (s->result == SCOPE_SUCCESS)
                s->result = f;

        if (s->result != SCOPE_SUCCESS)
                log_unit_warning(UNIT(s), "Failed with result '%s'.", scope_result_to_string(s->result));

        scope_set_state(s, s->result != SCOPE_SUCCESS ? SCOPE_FAILED : SCOPE_DEAD);
}
Exemplo n.º 9
0
static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
        bool skip_signal = false;
        int r;

        assert(s);

        if (s->result == SCOPE_SUCCESS)
                s->result = f;

        /* Before sending any signal, make sure we track all members of this cgroup */
        (void) unit_watch_all_pids(UNIT(s));

        /* Also, enqueue a job that we recheck all our PIDs a bit later, given that it's likely some processes have
         * died now */
        (void) unit_enqueue_rewatch_pids(UNIT(s));

        /* If we have a controller set let's ask the controller nicely to terminate the scope, instead of us going
         * directly into SIGTERM berserk mode */
        if (state == SCOPE_STOP_SIGTERM)
                skip_signal = bus_scope_send_request_stop(s) > 0;

        if (skip_signal)
                r = 1; /* wait */
        else {
                r = unit_kill_context(
                                UNIT(s),
                                &s->kill_context,
                                state != SCOPE_STOP_SIGTERM ? KILL_KILL :
                                s->was_abandoned            ? KILL_TERMINATE_AND_LOG :
                                                              KILL_TERMINATE,
                                -1, -1, false);
                if (r < 0)
                        goto fail;
        }

        if (r > 0) {
                r = scope_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_stop_usec));
                if (r < 0)
                        goto fail;

                scope_set_state(s, state);
        } else if (state == SCOPE_STOP_SIGTERM)
                scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_SUCCESS);
        else
                scope_enter_dead(s, SCOPE_SUCCESS);

        return;

fail:
        log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m");

        scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
}
Exemplo n.º 10
0
static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
        bool skip_signal = false;
        int r;

        assert(s);

        if (s->result == SCOPE_SUCCESS)
                s->result = f;

        unit_watch_all_pids(UNIT(s));

        /* If we have a controller set let's ask the controller nicely
         * to terminate the scope, instead of us going directly into
         * SIGTERM berserk mode */
        if (state == SCOPE_STOP_SIGTERM)
                skip_signal = bus_scope_send_request_stop(s) > 0;

        if (skip_signal)
                r = 1; /* wait */
        else {
                r = unit_kill_context(
                                UNIT(s),
                                &s->kill_context,
                                state != SCOPE_STOP_SIGTERM ? KILL_KILL :
                                s->was_abandoned            ? KILL_TERMINATE_AND_LOG :
                                                              KILL_TERMINATE,
                                -1, -1, false);
                if (r < 0)
                        goto fail;
        }

        if (r > 0) {
                r = scope_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_stop_usec));
                if (r < 0)
                        goto fail;

                scope_set_state(s, state);
        } else if (state == SCOPE_STOP_SIGTERM)
                scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_SUCCESS);
        else
                scope_enter_dead(s, SCOPE_SUCCESS);

        return;

fail:
        log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m");

        scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
}
Exemplo n.º 11
0
static int scope_start(Unit *u) {
        Scope *s = SCOPE(u);
        int r;

        assert(s);

        if (unit_has_name(u, SPECIAL_INIT_SCOPE))
                return -EPERM;

        if (s->state == SCOPE_FAILED)
                return -EPERM;

        /* We can't fulfill this right now, please try again later */
        if (IN_SET(s->state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
                return -EAGAIN;

        assert(s->state == SCOPE_DEAD);

        if (!u->transient && !MANAGER_IS_RELOADING(u->manager))
                return -ENOENT;

        (void) bus_scope_track_controller(s);

        r = unit_acquire_invocation_id(u);
        if (r < 0)
                return r;

        (void) unit_realize_cgroup(u);
        (void) unit_reset_cpu_accounting(u);
        (void) unit_reset_ip_accounting(u);

        unit_export_state_files(UNIT(s));

        r = unit_attach_pids_to_cgroup(u, UNIT(s)->pids, NULL);
        if (r < 0) {
                log_unit_warning_errno(UNIT(s), r, "Failed to add PIDs to scope's control group: %m");
                scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
                return r;
        }

        s->result = SCOPE_SUCCESS;

        scope_set_state(s, SCOPE_RUNNING);

        /* Start watching the PIDs currently in the scope */
        (void) unit_enqueue_rewatch_pids(UNIT(s));
        return 1;
}
Exemplo n.º 12
0
static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
        bool skip_signal = false;
        int r;

        assert(s);

        if (f != SCOPE_SUCCESS)
                s->result = f;

        unit_watch_all_pids(UNIT(s));

        /* If we have a controller set let's ask the controller nicely
         * to terminate the scope, instead of us going directly into
         * SIGTERM beserk mode */
        if (state == SCOPE_STOP_SIGTERM)
                skip_signal = bus_scope_send_request_stop(s) > 0;

        if (!skip_signal) {
                r = unit_kill_context(
                                UNIT(s),
                                &s->kill_context,
                                state != SCOPE_STOP_SIGTERM,
                                -1, -1, false);
                if (r < 0)
                        goto fail;
        } else
                r = 1;

        if (r > 0) {
                r = scope_arm_timer(s);
                if (r < 0)
                        goto fail;

                scope_set_state(s, state);
        } else if (state == SCOPE_STOP_SIGTERM)
                scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_SUCCESS);
        else
                scope_enter_dead(s, SCOPE_SUCCESS);

        return;

fail:
        log_warning_unit(UNIT(s)->id,
                         "%s failed to kill processes: %s", UNIT(s)->id, strerror(-r));

        scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
}
Exemplo n.º 13
0
static int scope_coldplug(Unit *u) {
        Scope *s = SCOPE(u);
        int r;

        assert(s);
        assert(s->state == SCOPE_DEAD);

        if (s->deserialized_state != s->state) {

                if (s->deserialized_state == SCOPE_STOP_SIGKILL || s->deserialized_state == SCOPE_STOP_SIGTERM) {
                        r = scope_arm_timer(s);
                        if (r < 0)
                                return r;
                }

                scope_set_state(s, s->deserialized_state);
        }

        return 0;
}
Exemplo n.º 14
0
int scope_abandon(Scope *s) {
        assert(s);

        if (unit_has_name(UNIT(s), SPECIAL_INIT_SCOPE))
                return -EPERM;

        if (!IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED))
                return -ESTALE;

        s->was_abandoned = true;

        s->controller = mfree(s->controller);
        s->controller_track = sd_bus_track_unref(s->controller_track);

        scope_set_state(s, SCOPE_ABANDONED);

        /* The client is no longer watching the remaining processes, so let's step in here, under the assumption that
         * the remaining processes will be sooner or later reassigned to us as parent. */
        (void) unit_enqueue_rewatch_pids(UNIT(s));

        return 0;
}
Exemplo n.º 15
0
static int scope_coldplug(Unit *u) {
        Scope *s = SCOPE(u);
        int r;

        assert(s);
        assert(s->state == SCOPE_DEAD);

        if (s->deserialized_state == s->state)
                return 0;

        if (IN_SET(s->deserialized_state, SCOPE_STOP_SIGKILL, SCOPE_STOP_SIGTERM)) {
                r = scope_arm_timer(s, usec_add(u->state_change_timestamp.monotonic, s->timeout_stop_usec));
                if (r < 0)
                        return r;
        }

        if (!IN_SET(s->deserialized_state, SCOPE_DEAD, SCOPE_FAILED))
                unit_watch_all_pids(UNIT(s));

        scope_set_state(s, s->deserialized_state);
        return 0;
}
Exemplo n.º 16
0
static int scope_coldplug(Unit *u) {
        Scope *s = SCOPE(u);
        int r;

        assert(s);
        assert(s->state == SCOPE_DEAD);

        if (s->deserialized_state != s->state) {

                if (IN_SET(s->deserialized_state, SCOPE_STOP_SIGKILL, SCOPE_STOP_SIGTERM)) {
                        r = scope_arm_timer(s);
                        if (r < 0)
                                return r;
                }

                if (!IN_SET(s->deserialized_state, SCOPE_DEAD, SCOPE_FAILED))
                        unit_watch_all_pids(UNIT(s));

                scope_set_state(s, s->deserialized_state);
        }

        return 0;
}