chiark / gitweb /
manager: clean environment before passing it on to others
[elogind.git] / src / core / job.c
index 31ab11880ef0fa1a52b4d4c6a9c628c6d8a56928..2bafbc15894b9a636b6d762698758aa5b8c05c41 100644 (file)
@@ -34,6 +34,9 @@
 #include "load-dropin.h"
 #include "log.h"
 #include "dbus-job.h"
+#include "special.h"
+#include "sync.h"
+#include "virt.h"
 
 JobBusClient* job_bus_client_new(DBusConnection *connection, const char *name) {
         JobBusClient *cl;
@@ -166,6 +169,7 @@ static void job_merge_into_installed(Job *j, Job *other) {
                 assert(other->type == JOB_NOP);
 
         j->override = j->override || other->override;
+        j->ignore_order = j->ignore_order || other->ignore_order;
 }
 
 Job* job_install(Job *j) {
@@ -713,25 +717,25 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) {
                 sd_id128_t mid;
 
                 mid = result == JOB_DONE ? SD_MESSAGE_UNIT_STARTED : SD_MESSAGE_UNIT_FAILED;
-                log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
+                log_struct_unit(result == JOB_DONE ? LOG_INFO : LOG_ERR,
+                           u->id,
                            MESSAGE_ID(mid),
-                           "UNIT=%s", u->id,
                            "RESULT=%s", job_result_to_string(result),
                            "MESSAGE=%s", buf,
                            NULL);
 
         } else if (t == JOB_STOP)
-                log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
+                log_struct_unit(result == JOB_DONE ? LOG_INFO : LOG_ERR,
+                           u->id,
                            MESSAGE_ID(SD_MESSAGE_UNIT_STOPPED),
-                           "UNIT=%s", u->id,
                            "RESULT=%s", job_result_to_string(result),
                            "MESSAGE=%s", buf,
                            NULL);
 
         else if (t == JOB_RELOAD)
-                log_struct(result == JOB_DONE ? LOG_INFO : LOG_ERR,
+                log_struct_unit(result == JOB_DONE ? LOG_INFO : LOG_ERR,
+                           u->id,
                            MESSAGE_ID(SD_MESSAGE_UNIT_RELOADED),
-                           "UNIT=%s", u->id,
                            "RESULT=%s", job_result_to_string(result),
                            "MESSAGE=%s", buf,
                            NULL);
@@ -818,8 +822,8 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
          * this context. And JOB_FAILURE is already handled by the
          * unit itself. */
         if (result == JOB_TIMEOUT || result == JOB_DEPENDENCY) {
-                log_struct(LOG_NOTICE,
-                           "UNIT=%s", u->id,
+                log_struct_unit(LOG_NOTICE,
+                           u->id,
                            "JOB_TYPE=%s", job_type_to_string(t),
                            "JOB_RESULT=%s", job_result_to_string(result),
                            "Job %s/%s failed with result '%s'.",
@@ -1060,6 +1064,29 @@ int job_coldplug(Job *j) {
         return 0;
 }
 
+void job_shutdown_magic(Job *j) {
+        assert(j);
+
+        /* The shutdown target gets some special treatment here: we
+         * tell the kernel to begin with flushing its disk caches, to
+         * optimize shutdown time a bit. Ideally we wouldn't hardcode
+         * this magic into PID 1. However all other processes aren't
+         * options either since they'd exit much sooner than PID 1 and
+         * asynchronous sync() would cause their exit to be
+         * delayed. */
+
+        if (!unit_has_name(j->unit, SPECIAL_SHUTDOWN_TARGET))
+                return;
+
+        if (j->type != JOB_START)
+                return;
+
+        if (detect_container(NULL) > 0)
+                return;
+
+        asynchronous_sync();
+}
+
 static const char* const job_state_table[_JOB_STATE_MAX] = {
         [JOB_WAITING] = "waiting",
         [JOB_RUNNING] = "running"