]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/job.c
Merge pull request #17732 from yuwata/core-use-synthetic_errno
[thirdparty/systemd.git] / src / core / job.c
index cda4f344b89c87dc04883970bc07a545ee7de700..f3c1a0283167532758525c8d20a094d7db2df7fe 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: LGPL-2.1+ */
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include <errno.h>
 
@@ -263,6 +263,10 @@ int job_install_deserialized(Job *j) {
                 return log_unit_debug_errno(j->unit, SYNTHETIC_ERRNO(EEXIST),
                                             "Unit already has a job installed. Not installing deserialized job.");
 
+        r = hashmap_ensure_allocated(&j->manager->jobs, NULL);
+        if (r < 0)
+                return r;
+
         r = hashmap_put(j->manager->jobs, UINT32_TO_PTR(j->id), j);
         if (r == -EEXIST)
                 return log_unit_debug_errno(j->unit, r, "Job ID %" PRIu32 " already used, cannot deserialize job.", j->id);
@@ -418,21 +422,21 @@ JobType job_type_collapse(JobType t, Unit *u) {
 
         case JOB_TRY_RESTART:
                 s = unit_active_state(u);
-                if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
+                if (!UNIT_IS_ACTIVE_OR_RELOADING(s))
                         return JOB_NOP;
 
                 return JOB_RESTART;
 
         case JOB_TRY_RELOAD:
                 s = unit_active_state(u);
-                if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
+                if (!UNIT_IS_ACTIVE_OR_RELOADING(s))
                         return JOB_NOP;
 
                 return JOB_RELOAD;
 
         case JOB_RELOAD_OR_START:
                 s = unit_active_state(u);
-                if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
+                if (!UNIT_IS_ACTIVE_OR_RELOADING(s))
                         return JOB_START;
 
                 return JOB_RELOAD;
@@ -454,7 +458,6 @@ int job_type_merge_and_collapse(JobType *a, JobType b, Unit *u) {
 }
 
 static bool job_is_runnable(Job *j) {
-        Iterator i;
         Unit *other;
         void *v;
 
@@ -478,13 +481,21 @@ static bool job_is_runnable(Job *j) {
         if (j->type == JOB_NOP)
                 return true;
 
-        HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i)
-                if (other->job && job_compare(j, other->job, UNIT_AFTER) > 0)
+        HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER])
+                if (other->job && job_compare(j, other->job, UNIT_AFTER) > 0) {
+                        log_unit_debug(j->unit,
+                                       "starting held back, waiting for: %s",
+                                       other->id);
                         return false;
+                }
 
-        HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i)
-                if (other->job && job_compare(j, other->job, UNIT_BEFORE) > 0)
+        HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE])
+                if (other->job && job_compare(j, other->job, UNIT_BEFORE) > 0) {
+                        log_unit_debug(j->unit,
+                                       "stopping held back, waiting for: %s",
+                                       other->id);
                         return false;
+                }
 
         return true;
 }
@@ -535,7 +546,7 @@ static void job_print_begin_status_message(Unit *u, JobType t) {
         format = job_get_begin_status_message_format(u, t);
 
         DISABLE_WARNING_FORMAT_NONLITERAL;
-        unit_status_printf(u, "", format);
+        unit_status_printf(u, STATUS_TYPE_NORMAL, "", format);
         REENABLE_WARNING;
 }
 
@@ -760,9 +771,15 @@ _pure_ static const char *job_get_done_status_message_format(Unit *u, JobType t,
         assert(t < _JOB_TYPE_MAX);
 
         if (IN_SET(t, JOB_START, JOB_STOP, JOB_RESTART)) {
+                const UnitStatusMessageFormats *formats = &UNIT_VTABLE(u)->status_message_formats;
+                if (formats->finished_job) {
+                        format = formats->finished_job(u, t, result);
+                        if (format)
+                                return format;
+                }
                 format = t == JOB_START ?
-                        UNIT_VTABLE(u)->status_message_formats.finished_start_job[result] :
-                        UNIT_VTABLE(u)->status_message_formats.finished_stop_job[result];
+                        formats->finished_start_job[result] :
+                        formats->finished_stop_job[result];
                 if (format)
                         return format;
         }
@@ -824,11 +841,10 @@ static void job_print_done_status_message(Unit *u, JobType t, JobResult result)
         else
                 status = job_print_done_status_messages[result].word;
 
-        if (result != JOB_DONE)
-                manager_flip_auto_status(u->manager, true);
-
         DISABLE_WARNING_FORMAT_NONLITERAL;
-        unit_status_printf(u, status, format);
+        unit_status_printf(u,
+                           result == JOB_DONE ? STATUS_TYPE_NORMAL : STATUS_TYPE_NOTICE,
+                           status, format);
         REENABLE_WARNING;
 
         if (t == JOB_START && result == JOB_FAILED) {
@@ -940,12 +956,11 @@ static void job_emit_done_status_message(Unit *u, uint32_t job_id, JobType t, Jo
 
 static void job_fail_dependencies(Unit *u, UnitDependency d) {
         Unit *other;
-        Iterator i;
         void *v;
 
         assert(u);
 
-        HASHMAP_FOREACH_KEY(v, other, u->dependencies[d], i) {
+        HASHMAP_FOREACH_KEY(v, other, u->dependencies[d]) {
                 Job *j = other->job;
 
                 if (!j)
@@ -961,7 +976,6 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool alr
         Unit *u;
         Unit *other;
         JobType t;
-        Iterator i;
         void *v;
 
         assert(j);
@@ -973,9 +987,10 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool alr
 
         j->result = result;
 
-        log_unit_debug(u, "Job %" PRIu32 " %s/%s finished, result=%s", j->id, u->id, job_type_to_string(t), job_result_to_string(result));
+        log_unit_debug(u, "Job %" PRIu32 " %s/%s finished, result=%s",
+                       j->id, u->id, job_type_to_string(t), job_result_to_string(result));
 
-        /* If this job did nothing to respective unit we don't log the status message */
+        /* If this job did nothing to the respective unit we don't log the status message */
         if (!already)
                 job_emit_done_status_message(u, j->id, t, result);
 
@@ -1012,7 +1027,7 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool alr
          * aren't active. This is when the verify-active job merges with a
          * satisfying job type, and then loses it's invalidation effect, as the
          * result there is JOB_DONE for the start job we merged into, while we
-         * should be failing the depending job if the said unit isn't infact
+         * should be failing the depending job if the said unit isn't in fact
          * active. Oneshots are an example of this, where going directly from
          * activating to inactive is success.
          *
@@ -1054,12 +1069,12 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool alr
 
 finish:
         /* Try to start the next jobs that can be started */
-        HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_AFTER], i)
+        HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_AFTER])
                 if (other->job) {
                         job_add_to_run_queue(other->job);
                         job_add_to_gc_queue(other->job);
                 }
-        HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BEFORE], i)
+        HASHMAP_FOREACH_KEY(v, other, u->dependencies[UNIT_BEFORE])
                 if (other->job) {
                         job_add_to_run_queue(other->job);
                         job_add_to_gc_queue(other->job);
@@ -1153,8 +1168,11 @@ void job_add_to_run_queue(Job *j) {
                         log_warning_errno(r, "Failed to enable job run queue event source, ignoring: %m");
         }
 
-        prioq_put(j->manager->run_queue, j, &j->run_queue_idx);
-        j->in_run_queue = true;
+        r = prioq_put(j->manager->run_queue, j, &j->run_queue_idx);
+        if (r < 0)
+                log_warning_errno(r, "Failed put job in run queue, ignoring: %m");
+        else
+                j->in_run_queue = true;
 }
 
 void job_add_to_dbus_queue(Job *j) {
@@ -1406,7 +1424,6 @@ int job_get_timeout(Job *j, usec_t *timeout) {
 
 bool job_may_gc(Job *j) {
         Unit *other;
-        Iterator i;
         void *v;
 
         assert(j);
@@ -1436,11 +1453,11 @@ bool job_may_gc(Job *j) {
                 return false;
 
         /* The logic is inverse to job_is_runnable, we cannot GC as long as we block any job. */
-        HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i)
+        HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE])
                 if (other->job && job_compare(j, other->job, UNIT_BEFORE) < 0)
                         return false;
 
-        HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i)
+        HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER])
                 if (other->job && job_compare(j, other->job, UNIT_AFTER) < 0)
                         return false;
 
@@ -1487,7 +1504,6 @@ int job_get_before(Job *j, Job*** ret) {
         _cleanup_free_ Job** list = NULL;
         size_t n = 0, n_allocated = 0;
         Unit *other = NULL;
-        Iterator i;
         void *v;
 
         /* Returns a list of all pending jobs that need to finish before this job may be started. */
@@ -1500,7 +1516,7 @@ int job_get_before(Job *j, Job*** ret) {
                 return 0;
         }
 
-        HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i) {
+        HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER]) {
                 if (!other->job)
                         continue;
                 if (job_compare(j, other->job, UNIT_AFTER) <= 0)
@@ -1511,7 +1527,7 @@ int job_get_before(Job *j, Job*** ret) {
                 list[n++] = other->job;
         }
 
-        HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i) {
+        HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE]) {
                 if (!other->job)
                         continue;
                 if (job_compare(j, other->job, UNIT_BEFORE) <= 0)
@@ -1534,14 +1550,13 @@ int job_get_after(Job *j, Job*** ret) {
         size_t n = 0, n_allocated = 0;
         Unit *other = NULL;
         void *v;
-        Iterator i;
 
         assert(j);
         assert(ret);
 
         /* Returns a list of all pending jobs that are waiting for this job to finish. */
 
-        HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i) {
+        HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE]) {
                 if (!other->job)
                         continue;
 
@@ -1556,7 +1571,7 @@ int job_get_after(Job *j, Job*** ret) {
                 list[n++] = other->job;
         }
 
-        HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i) {
+        HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER]) {
                 if (!other->job)
                         continue;
 
@@ -1607,6 +1622,7 @@ static const char* const job_mode_table[_JOB_MODE_MAX] = {
         [JOB_FLUSH] = "flush",
         [JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies",
         [JOB_IGNORE_REQUIREMENTS] = "ignore-requirements",
+        [JOB_TRIGGERING] = "triggering",
 };
 
 DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode);