chiark / gitweb /
unit: make sure a job for a service of type 'finish' succeeds if the process terminat...
[elogind.git] / src / unit.c
index 50f3b8fabd5f76266e0c50d66618763c197b17d6..b93777bec68dac245d3d3a87b5d7a036c43278dc 100644 (file)
@@ -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,8 +630,8 @@ 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 (u->meta.following)
-                fprintf(f, "%s\tFollowing: %s\n", prefix, u->meta.following->meta.id);
+        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);
@@ -645,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));
 
@@ -933,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) {
@@ -1023,7 +1034,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;
@@ -1036,7 +1049,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);
                                 }
                         }
 
@@ -1046,7 +1061,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;
@@ -1087,12 +1102,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
@@ -1100,17 +1114,12 @@ 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_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);
 
-                if (u->meta.type == UNIT_TARGET)
-                        /* A target got activated, maybe this is a runlevel? */
-                        manager_write_utmp_runlevel(u->meta.manager, u);
-
-        } else if (!UNIT_IS_ACTIVE_OR_RELOADING(ns)) {
+        } else {
 
                 if (unit_has_name(u, SPECIAL_SYSLOG_SERVICE))
                         /* The syslog daemon might just have
@@ -1120,6 +1129,13 @@ 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))
+
+                        /* Write audit record if we have just finished shutting down */
+                        manager_send_unit_audit(u->meta.manager, u, AUDIT_SERVICE_STOP, ns == UNIT_INACTIVE);
         }
 
         /* Maybe we finished startup and are now ready for being
@@ -1311,7 +1327,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,
@@ -1550,6 +1567,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;
 
@@ -2081,6 +2101,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",
@@ -2125,6 +2154,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",