X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Funit.c;h=33e9cef86508cc9a6f902de10e1426aac69847a0;hb=eaf91020117150567aee61d1324067c307e18950;hp=5807e4f4d1cbd2432ab48e07d829a363641a9984;hpb=5632e3743db350a67478acc107d76cdf648a1f99;p=elogind.git diff --git a/src/unit.c b/src/unit.c index 5807e4f4d..33e9cef86 100644 --- a/src/unit.c +++ b/src/unit.c @@ -41,6 +41,7 @@ #include "dbus-unit.h" #include "special.h" #include "cgroup-util.h" +#include "missing.h" const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = { [UNIT_SERVICE] = &service_vtable, @@ -235,6 +236,9 @@ bool unit_check_gc(Unit *u) { if (UNIT_VTABLE(u)->no_gc) return true; + if (u->meta.no_gc) + return true; + if (u->meta.job) return true; @@ -589,6 +593,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { timestamp3[FORMAT_TIMESTAMP_MAX], timestamp4[FORMAT_TIMESTAMP_MAX], timespan[FORMAT_TIMESPAN_MAX]; + Unit *following; assert(u); assert(u->meta.type >= 0); @@ -625,6 +630,9 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { SET_FOREACH(t, u->meta.names, i) fprintf(f, "%s\tName: %s\n", prefix, t); + if ((following = unit_following(u))) + fprintf(f, "%s\tFollowing: %s\n", prefix, following->meta.id); + if (u->meta.fragment_path) fprintf(f, "%s\tFragment Path: %s\n", prefix, u->meta.fragment_path); @@ -642,12 +650,14 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { fprintf(f, "%s\tRecursive Stop: %s\n" "%s\tStopWhenUnneeded: %s\n" - "%s\tOnlyByDependency: %s\n" + "%s\tRefuseManualStart: %s\n" + "%s\tRefuseManualStop: %s\n" "%s\tDefaultDependencies: %s\n" "%s\tIgnoreDependencyFailure: %s\n", prefix, yes_no(u->meta.recursive_stop), prefix, yes_no(u->meta.stop_when_unneeded), - prefix, yes_no(u->meta.only_by_dependency), + prefix, yes_no(u->meta.refuse_manual_start), + prefix, yes_no(u->meta.refuse_manual_stop), prefix, yes_no(u->meta.default_dependencies), prefix, yes_no(u->meta.ignore_dependency_failure)); @@ -930,6 +940,10 @@ static void retroactively_start_dependencies(Unit *u) { SET_FOREACH(other, u->meta.dependencies[UNIT_CONFLICTS], i) if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other))) manager_add_job(u->meta.manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL); + + SET_FOREACH(other, u->meta.dependencies[UNIT_CONFLICTED_BY], i) + if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other))) + manager_add_job(u->meta.manager, JOB_STOP, other, JOB_REPLACE, true, NULL, NULL); } static void retroactively_stop_dependencies(Unit *u) { @@ -976,8 +990,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) { * even if they might map to the same high-level * UnitActiveState! That means that ns == os is OK an expected * behaviour here. For example: if a mount point is remounted - * this function will be called too and the utmp code below - * relies on that! */ + * this function will be called too! */ dual_timestamp_get(&ts); @@ -1020,7 +1033,9 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) { job_finish_and_invalidate(u->meta.job, true); else if (u->meta.job->state == JOB_RUNNING && ns != UNIT_ACTIVATING) { unexpected = true; - job_finish_and_invalidate(u->meta.job, false); + + if (UNIT_IS_INACTIVE_OR_MAINTENANCE(ns)) + job_finish_and_invalidate(u->meta.job, ns != UNIT_MAINTENANCE); } break; @@ -1033,7 +1048,9 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) { job_finish_and_invalidate(u->meta.job, true); else if (ns != UNIT_ACTIVATING && ns != UNIT_RELOADING) { unexpected = true; - job_finish_and_invalidate(u->meta.job, false); + + if (UNIT_IS_INACTIVE_OR_MAINTENANCE(ns)) + job_finish_and_invalidate(u->meta.job, ns != UNIT_MAINTENANCE); } } @@ -1043,7 +1060,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) { case JOB_RESTART: case JOB_TRY_RESTART: - if (ns == UNIT_INACTIVE || ns == UNIT_MAINTENANCE) + if (UNIT_IS_INACTIVE_OR_MAINTENANCE(ns)) job_finish_and_invalidate(u->meta.job, true); else if (u->meta.job->state == JOB_RUNNING && ns != UNIT_DEACTIVATING) { unexpected = true; @@ -1084,12 +1101,11 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) { /* Some names are special */ if (UNIT_IS_ACTIVE_OR_RELOADING(ns)) { - if (unit_has_name(u, SPECIAL_DBUS_SERVICE)) { + if (unit_has_name(u, SPECIAL_DBUS_SERVICE)) /* The bus just might have become available, * hence try to connect to it, if we aren't * yet connected. */ bus_init(u->meta.manager); - } if (unit_has_name(u, SPECIAL_SYSLOG_SERVICE)) /* The syslog daemon just might have become @@ -1097,17 +1113,14 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) { * we aren't yet connected. */ log_open(); - if (u->meta.type == UNIT_MOUNT) - /* Another directory became available, let's - * check if that is enough to write our utmp - * entry. */ - manager_write_utmp_reboot(u->meta.manager); - - if (u->meta.type == UNIT_TARGET) - /* A target got activated, maybe this is a runlevel? */ - manager_write_utmp_runlevel(u->meta.manager, u); + if (u->meta.type == UNIT_SERVICE && + !UNIT_IS_ACTIVE_OR_RELOADING(os)) { + /* Write audit record if we have just finished starting up */ + manager_send_unit_audit(u->meta.manager, u, AUDIT_SERVICE_START, 1); + u->meta.in_audit = true; + } - } else if (!UNIT_IS_ACTIVE_OR_RELOADING(ns)) { + } else { if (unit_has_name(u, SPECIAL_SYSLOG_SERVICE)) /* The syslog daemon might just have @@ -1117,6 +1130,25 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) { /* We don't care about D-Bus here, since we'll get an * asynchronous notification for it anyway. */ + + if (u->meta.type == UNIT_SERVICE && + UNIT_IS_INACTIVE_OR_MAINTENANCE(ns) && + !UNIT_IS_INACTIVE_OR_MAINTENANCE(os)) { + + /* Hmm, if there was no start record written + * write it now, so that we always have a nice + * pair */ + if (!u->meta.in_audit) { + manager_send_unit_audit(u->meta.manager, u, AUDIT_SERVICE_START, ns == UNIT_INACTIVE); + + if (ns == UNIT_INACTIVE) + manager_send_unit_audit(u->meta.manager, u, AUDIT_SERVICE_STOP, true); + } else + /* Write audit record if we have just finished shutting down */ + manager_send_unit_audit(u->meta.manager, u, AUDIT_SERVICE_STOP, ns == UNIT_INACTIVE); + + u->meta.in_audit = false; + } } /* Maybe we finished startup and are now ready for being @@ -1308,7 +1340,8 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen [UNIT_REQUIRED_BY] = _UNIT_DEPENDENCY_INVALID, [UNIT_REQUIRED_BY_OVERRIDABLE] = _UNIT_DEPENDENCY_INVALID, [UNIT_WANTED_BY] = _UNIT_DEPENDENCY_INVALID, - [UNIT_CONFLICTS] = UNIT_CONFLICTS, + [UNIT_CONFLICTS] = UNIT_CONFLICTED_BY, + [UNIT_CONFLICTED_BY] = UNIT_CONFLICTS, [UNIT_BEFORE] = UNIT_AFTER, [UNIT_AFTER] = UNIT_BEFORE, [UNIT_ON_FAILURE] = _UNIT_DEPENDENCY_INVALID, @@ -1547,6 +1580,9 @@ char *unit_dbus_path(Unit *u) { assert(u); + if (!u->meta.id) + return NULL; + if (!(e = bus_path_escape(u->meta.id))) return NULL; @@ -2078,6 +2114,15 @@ void unit_reset_maintenance(Unit *u) { UNIT_VTABLE(u)->reset_maintenance(u); } +Unit *unit_following(Unit *u) { + assert(u); + + if (UNIT_VTABLE(u)->following) + return UNIT_VTABLE(u)->following(u); + + return NULL; +} + static const char* const unit_type_table[_UNIT_TYPE_MAX] = { [UNIT_SERVICE] = "service", [UNIT_TIMER] = "timer", @@ -2122,6 +2167,7 @@ static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = { [UNIT_REQUIRED_BY_OVERRIDABLE] = "RequiredByOverridable", [UNIT_WANTED_BY] = "WantedBy", [UNIT_CONFLICTS] = "Conflicts", + [UNIT_CONFLICTED_BY] = "ConflictedBy", [UNIT_BEFORE] = "Before", [UNIT_AFTER] = "After", [UNIT_REFERENCES] = "References",