diff options
Diffstat (limited to 'src/core/unit.c')
-rw-r--r-- | src/core/unit.c | 92 |
1 files changed, 52 insertions, 40 deletions
diff --git a/src/core/unit.c b/src/core/unit.c index 1c1d9cf896..e380276d49 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -85,12 +85,13 @@ Unit *unit_new(Manager *m, size_t size) { u->manager = m; u->type = _UNIT_TYPE_INVALID; - u->deserialized_job = _JOB_TYPE_INVALID; u->default_dependencies = true; u->unit_file_state = _UNIT_FILE_STATE_INVALID; u->unit_file_preset = -1; u->on_failure_job_mode = JOB_REPLACE; + RATELIMIT_INIT(u->auto_stop_ratelimit, 10 * USEC_PER_SEC, 16); + return u; } @@ -1092,6 +1093,8 @@ static int unit_add_target_dependencies(Unit *u) { static const UnitDependency deps[] = { UNIT_REQUIRED_BY, UNIT_REQUIRED_BY_OVERRIDABLE, + UNIT_REQUISITE_OF, + UNIT_REQUISITE_OF_OVERRIDABLE, UNIT_WANTED_BY, UNIT_BOUND_BY }; @@ -1589,8 +1592,20 @@ bool unit_can_reload(Unit *u) { } static void unit_check_unneeded(Unit *u) { - Iterator i; + + static const UnitDependency needed_dependencies[] = { + UNIT_REQUIRED_BY, + UNIT_REQUIRED_BY_OVERRIDABLE, + UNIT_REQUISITE, + UNIT_REQUISITE_OF_OVERRIDABLE, + UNIT_WANTED_BY, + UNIT_BOUND_BY, + }; + Unit *other; + Iterator i; + unsigned j; + int r; assert(u); @@ -1603,32 +1618,32 @@ static void unit_check_unneeded(Unit *u) { if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u))) return; - SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i) - if (unit_active_or_pending(other)) - return; - - SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i) - if (unit_active_or_pending(other)) - return; + for (j = 0; j < ELEMENTSOF(needed_dependencies); j++) + SET_FOREACH(other, u->dependencies[needed_dependencies[j]], i) + if (unit_active_or_pending(other)) + return; - SET_FOREACH(other, u->dependencies[UNIT_WANTED_BY], i) - if (unit_active_or_pending(other)) - return; - - SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i) - if (unit_active_or_pending(other)) - return; + /* If stopping a unit fails continously we might enter a stop + * loop here, hence stop acting on the service being + * unnecessary after a while. */ + if (!ratelimit_test(&u->auto_stop_ratelimit)) { + log_unit_warning(u, "Unit not needed anymore, but not stopping since we tried this too often recently."); + return; + } log_unit_info(u, "Unit not needed anymore. Stopping."); /* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */ - manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, true, NULL, NULL); + r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, true, NULL, NULL); + if (r < 0) + log_unit_warning_errno(u, r, "Failed to enqueue stop job, ignoring: %m"); } static void unit_check_binds_to(Unit *u) { bool stop = false; Unit *other; Iterator i; + int r; assert(u); @@ -1652,11 +1667,21 @@ static void unit_check_binds_to(Unit *u) { if (!stop) return; + /* If stopping a unit fails continously we might enter a stop + * loop here, hence stop acting on the service being + * unnecessary after a while. */ + if (!ratelimit_test(&u->auto_stop_ratelimit)) { + log_unit_warning(u, "Unit is bound to inactive unit %s, but not stopping since we tried this too often recently.", other->id); + return; + } + assert(other); log_unit_info(u, "Unit is bound to inactive unit %s. Stopping, too.", other->id); /* A unit we need to run is gone. Sniff. Let's stop this. */ - manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, true, NULL, NULL); + r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, true, NULL, NULL); + if (r < 0) + log_unit_warning_errno(u, r, "Failed to enqueue stop job, ignoring: %m"); } static void retroactively_start_dependencies(Unit *u) { @@ -2163,13 +2188,15 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen [UNIT_REQUIRES] = UNIT_REQUIRED_BY, [UNIT_REQUIRES_OVERRIDABLE] = UNIT_REQUIRED_BY_OVERRIDABLE, [UNIT_WANTS] = UNIT_WANTED_BY, - [UNIT_REQUISITE] = UNIT_REQUIRED_BY, - [UNIT_REQUISITE_OVERRIDABLE] = UNIT_REQUIRED_BY_OVERRIDABLE, + [UNIT_REQUISITE] = UNIT_REQUISITE_OF, + [UNIT_REQUISITE_OVERRIDABLE] = UNIT_REQUISITE_OF_OVERRIDABLE, [UNIT_BINDS_TO] = UNIT_BOUND_BY, [UNIT_PART_OF] = UNIT_CONSISTS_OF, - [UNIT_REQUIRED_BY] = _UNIT_DEPENDENCY_INVALID, - [UNIT_REQUIRED_BY_OVERRIDABLE] = _UNIT_DEPENDENCY_INVALID, - [UNIT_WANTED_BY] = _UNIT_DEPENDENCY_INVALID, + [UNIT_REQUIRED_BY] = UNIT_REQUIRES, + [UNIT_REQUIRED_BY_OVERRIDABLE] = UNIT_REQUIRES_OVERRIDABLE, + [UNIT_REQUISITE_OF] = UNIT_REQUISITE, + [UNIT_REQUISITE_OF_OVERRIDABLE] = UNIT_REQUISITE_OVERRIDABLE, + [UNIT_WANTED_BY] = UNIT_WANTS, [UNIT_BOUND_BY] = UNIT_BINDS_TO, [UNIT_CONSISTS_OF] = UNIT_PART_OF, [UNIT_CONFLICTS] = UNIT_CONFLICTED_BY, @@ -2713,16 +2740,8 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { job_free(j); return r; } - } else { - /* legacy */ - JobType type; - - type = job_type_from_string(v); - if (type < 0) - log_unit_debug(u, "Failed to parse job type value: %s", v); - else - u->deserialized_job = type; - } + } else /* legacy for pre-44 */ + log_unit_warning(u, "Update from too old systemd versions are unsupported, cannot deserialize job: %s", v); continue; } else if (streq(l, "inactive-exit-timestamp")) { dual_timestamp_deserialize(v, &u->inactive_exit_timestamp); @@ -2871,13 +2890,6 @@ int unit_coldplug(Unit *u) { r = job_coldplug(u->job); if (r < 0) return r; - } else if (u->deserialized_job >= 0) { - /* legacy */ - r = manager_add_job(u->manager, u->deserialized_job, u, JOB_IGNORE_REQUIREMENTS, false, NULL, NULL); - if (r < 0) - return r; - - u->deserialized_job = _JOB_TYPE_INVALID; } return 0; |