[systemd-commits] 5 commits - man/systemctl.xml man/systemd-run.xml man/systemd.network.xml src/core src/libsystemd src/run

Lennart Poettering lennart at kemper.freedesktop.org
Tue Apr 28 03:34:25 PDT 2015


 man/systemctl.xml                |    4 +-
 man/systemd-run.xml              |   12 ++++++
 man/systemd.network.xml          |    3 +
 src/core/execute.c               |    3 +
 src/core/scope.c                 |    6 ++-
 src/libsystemd/sd-bus/bus-util.c |   44 +++++++++++++++-------
 src/libsystemd/sd-bus/bus-util.h |    1 
 src/run/run.c                    |   78 +++++++++++++++++++++++++++++++++------
 8 files changed, 121 insertions(+), 30 deletions(-)

New commits:
commit 3d161f991e16369aa59f447eb4cdb90af33261c8
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Apr 28 12:33:19 2015 +0200

    run: by default, wait until the transient unit finished start-up
    
    Make this blocking behaviour optional with --no-block, similar to
    systemctl's switch of this name.

diff --git a/man/systemctl.xml b/man/systemctl.xml
index 8c0a01d..4e77af5 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -316,8 +316,8 @@
           <para>Do not synchronously wait for the requested operation
           to finish. If this is not specified, the job will be
           verified, enqueued and <command>systemctl</command> will
-          wait until it is completed. By passing this argument, it is
-          only verified and enqueued.</para>
+          wait until the unit's start-up is completed. By passing this
+          argument, it is only verified and enqueued.</para>
         </listitem>
       </varlistentry>
 
diff --git a/man/systemd-run.xml b/man/systemd-run.xml
index 629bc4a..71b365c 100644
--- a/man/systemd-run.xml
+++ b/man/systemd-run.xml
@@ -294,6 +294,18 @@
         <command>set-property</command> command.</para> </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--no-block</option></term>
+
+        <listitem>
+          <para>Do not synchronously wait for the requested operation
+          to finish. If this is not specified, the job will be
+          verified, enqueued and <command>systemd-run</command> will
+          wait until the unit's start-up is completed. By passing this
+          argument, it is only verified and enqueued.</para>
+        </listitem>
+      </varlistentry>
+
       <xi:include href="user-system-options.xml" xpointer="user" />
       <xi:include href="user-system-options.xml" xpointer="system" />
       <xi:include href="user-system-options.xml" xpointer="host" />
diff --git a/src/run/run.c b/src/run/run.c
index 85fe29b..db15ab6 100644
--- a/src/run/run.c
+++ b/src/run/run.c
@@ -38,6 +38,7 @@
 
 static bool arg_scope = false;
 static bool arg_remain_after_exit = false;
+static bool arg_no_block = false;
 static const char *arg_unit = NULL;
 static const char *arg_description = NULL;
 static const char *arg_slice = NULL;
@@ -77,6 +78,7 @@ static void help(void) {
                "  -p --property=NAME=VALUE        Set unit property\n"
                "     --description=TEXT           Description for unit\n"
                "     --slice=SLICE                Run in the specified slice\n"
+               "     --no-block                   Do not wait until operation finished\n"
                "  -r --remain-after-exit          Leave service around until explicitly stopped\n"
                "     --send-sighup                Send SIGHUP when terminating\n"
                "     --service-type=TYPE          Service type\n"
@@ -124,7 +126,8 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_ON_UNIT_ACTIVE,
                 ARG_ON_UNIT_INACTIVE,
                 ARG_ON_CALENDAR,
-                ARG_TIMER_PROPERTY
+                ARG_TIMER_PROPERTY,
+                ARG_NO_BLOCK,
         };
 
         static const struct option options[] = {
@@ -155,6 +158,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "on-unit-inactive",  required_argument, NULL, ARG_ON_UNIT_INACTIVE },
                 { "on-calendar",       required_argument, NULL, ARG_ON_CALENDAR      },
                 { "timer-property",    required_argument, NULL, ARG_TIMER_PROPERTY   },
+                { "no-block",          no_argument,       NULL, ARG_NO_BLOCK         },
                 {},
         };
 
@@ -329,6 +333,10 @@ static int parse_argv(int argc, char *argv[]) {
 
                         break;
 
+                case ARG_NO_BLOCK:
+                        arg_no_block = true;
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -651,8 +659,9 @@ static int start_transient_service(
                 sd_bus *bus,
                 char **argv) {
 
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
         _cleanup_free_ char *service = NULL, *pty_path = NULL;
         _cleanup_close_ int master = -1;
         int r;
@@ -673,7 +682,6 @@ static int start_transient_service(
 
                 } else if (arg_transport == BUS_TRANSPORT_MACHINE) {
                         _cleanup_bus_unref_ sd_bus *system_bus = NULL;
-                        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
                         const char *s;
 
                         r = sd_bus_open_system(&system_bus);
@@ -697,6 +705,8 @@ static int start_transient_service(
                         if (r < 0)
                                 return bus_log_parse_error(r);
 
+                        reply = sd_bus_message_unref(reply);
+
                         master = fcntl(master, F_DUPFD_CLOEXEC, 3);
                         if (master < 0)
                                 return log_error_errno(errno, "Failed to duplicate master fd: %m");
@@ -711,6 +721,12 @@ static int start_transient_service(
                         return log_error_errno(errno, "Failed to unlock tty: %m");
         }
 
+        if (!arg_no_block) {
+                r = bus_wait_for_jobs_new(bus, &w);
+                if (r < 0)
+                        return log_error_errno(r, "Could not watch jobs: %m");
+        }
+
         if (arg_unit) {
                 service = unit_name_mangle_with_suffix(arg_unit, MANGLE_NOGLOB, ".service");
                 if (!service)
@@ -751,12 +767,24 @@ static int start_transient_service(
         if (r < 0)
                 return bus_log_create_error(r);
 
-        r = sd_bus_call(bus, m, 0, &error, NULL);
+        r = sd_bus_call(bus, m, 0, &error, &reply);
         if (r < 0) {
                 log_error("Failed to start transient service unit: %s", bus_error_message(&error, -r));
                 return r;
         }
 
+        if (w) {
+                const char *object;
+
+                r = sd_bus_message_read(reply, "o", &object);
+                if (r < 0)
+                        return bus_log_parse_error(r);
+
+                r = bus_wait_for_jobs_one(w, object, arg_quiet);
+                if (r < 0)
+                        return r;
+        }
+
         if (master >= 0) {
                 _cleanup_(pty_forward_freep) PTYForward *forward = NULL;
                 _cleanup_event_unref_ sd_event *event = NULL;

commit de158ed22db60e3a6654557fa4aa72f7248550af
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Apr 28 12:21:31 2015 +0200

    run: synchronously wait until the scope unit we create is started
    
    Otherwise it might happen that by the time PID 1 adds our process to the
    scope unit the process might already have died, if the process is
    short-running (such as an invocation to /bin/true).
    
    https://bugs.freedesktop.org/show_bug.cgi?id=86520

diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c
index a30493f..258265d 100644
--- a/src/libsystemd/sd-bus/bus-util.c
+++ b/src/libsystemd/sd-bus/bus-util.c
@@ -1887,6 +1887,16 @@ int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) {
         return set_put_strdup(d->jobs, path);
 }
 
+int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet) {
+        int r;
+
+        r = bus_wait_for_jobs_add(d, path);
+        if (r < 0)
+                return log_oom();
+
+        return bus_wait_for_jobs(d, quiet);
+}
+
 int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet) {
         const char *type, *path, *source;
         int r;
diff --git a/src/libsystemd/sd-bus/bus-util.h b/src/libsystemd/sd-bus/bus-util.h
index b97729e..0f7a3b2 100644
--- a/src/libsystemd/sd-bus/bus-util.h
+++ b/src/libsystemd/sd-bus/bus-util.h
@@ -207,6 +207,7 @@ int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret);
 void bus_wait_for_jobs_free(BusWaitForJobs *d);
 int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path);
 int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet);
+int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet);
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(BusWaitForJobs*, bus_wait_for_jobs_free);
 
diff --git a/src/run/run.c b/src/run/run.c
index 156824e..85fe29b 100644
--- a/src/run/run.c
+++ b/src/run/run.c
@@ -803,14 +803,20 @@ static int start_transient_scope(
                 char **argv) {
 
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+        _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
         _cleanup_strv_free_ char **env = NULL, **user_env = NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
         _cleanup_free_ char *scope = NULL;
+        const char *object = NULL;
         int r;
 
         assert(bus);
         assert(argv);
 
+        r = bus_wait_for_jobs_new(bus, &w);
+        if (r < 0)
+                return log_oom();
+
         if (arg_unit) {
                 scope = unit_name_mangle_with_suffix(arg_unit, MANGLE_NOGLOB, ".scope");
                 if (!scope)
@@ -851,7 +857,7 @@ static int start_transient_scope(
         if (r < 0)
                 return bus_log_create_error(r);
 
-        r = sd_bus_call(bus, m, 0, &error, NULL);
+        r = sd_bus_call(bus, m, 0, &error, &reply);
         if (r < 0) {
                 log_error("Failed to start transient scope unit: %s", bus_error_message(&error, -r));
                 return r;
@@ -911,8 +917,16 @@ static int start_transient_scope(
         if (!env)
                 return log_oom();
 
+        r = sd_bus_message_read(reply, "o", &object);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        r = bus_wait_for_jobs_one(w, object, arg_quiet);
+        if (r < 0)
+                return r;
+
         if (!arg_quiet)
-                log_info("Running as unit %s.", scope);
+                log_info("Running scope as unit %s.", scope);
 
         execvpe(argv[0], argv, env);
 
@@ -924,13 +938,19 @@ static int start_transient_timer(
                 char **argv) {
 
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
+        _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
         _cleanup_free_ char *timer = NULL, *service = NULL;
+        const char *object = NULL;
         int r;
 
         assert(bus);
         assert(argv);
 
+        r = bus_wait_for_jobs_new(bus, &w);
+        if (r < 0)
+                return log_oom();
+
         if (arg_unit) {
                 switch(unit_name_to_type(arg_unit)) {
 
@@ -1031,15 +1051,23 @@ static int start_transient_timer(
         if (r < 0)
                 return bus_log_create_error(r);
 
-        r = sd_bus_call(bus, m, 0, &error, NULL);
+        r = sd_bus_call(bus, m, 0, &error, &reply);
         if (r < 0) {
                 log_error("Failed to start transient timer unit: %s", bus_error_message(&error, -r));
                 return r;
         }
 
-        log_info("Running as unit %s.", timer);
+        r = sd_bus_message_read(reply, "o", &object);
+        if (r < 0)
+                return bus_log_parse_error(r);
+
+        r = bus_wait_for_jobs_one(w, object, arg_quiet);
+        if (r < 0)
+                return r;
+
+        log_info("Running timer as unit %s.", timer);
         if (argv[0])
-                log_info("Will run as unit %s.", service);
+                log_info("Will run service as unit %s.", service);
 
         return 0;
 }

commit dd305ec9c6c2ef6e0b5e43de388a98825385b359
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Apr 28 12:20:29 2015 +0200

    core: when we cannot add PID to a scope cgroup, log about it
    
    Also, place the scope unit in failed state.

diff --git a/src/core/execute.c b/src/core/execute.c
index bbd0d2c..9eba323 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -1809,6 +1809,7 @@ static int exec_child(
                         log_close();
                 }
         }
+
         execve(command->path, final_argv, final_env);
         *exit_status = EXIT_EXEC;
         return -errno;
@@ -1903,7 +1904,7 @@ int exec_spawn(ExecCommand *command,
          * sure that when we kill the cgroup the process will be
          * killed too). */
         if (params->cgroup_path)
-                cg_attach(SYSTEMD_CGROUP_CONTROLLER, params->cgroup_path, pid);
+                (void) cg_attach(SYSTEMD_CGROUP_CONTROLLER, params->cgroup_path, pid);
 
         exec_status_start(&command->exec_status, pid);
 
diff --git a/src/core/scope.c b/src/core/scope.c
index 1c3c6bb..1848641 100644
--- a/src/core/scope.c
+++ b/src/core/scope.c
@@ -277,6 +277,7 @@ static int scope_start(Unit *u) {
         if (s->state == SCOPE_FAILED)
                 return -EPERM;
 
+        /* We can't fulfill this right now, please try again later */
         if (s->state == SCOPE_STOP_SIGTERM ||
             s->state == SCOPE_STOP_SIGKILL)
                 return -EAGAIN;
@@ -290,8 +291,11 @@ static int scope_start(Unit *u) {
         (void) unit_reset_cpu_usage(u);
 
         r = unit_attach_pids_to_cgroup(u);
-        if (r < 0)
+        if (r < 0) {
+                log_unit_warning_errno(UNIT(s)->id, r, "%s: Failed to add PIDs to scope's control group: %m", UNIT(s)->id);
+                scope_enter_dead(s, SERVICE_FAILURE_RESOURCES);
                 return r;
+        }
 
         s->result = SCOPE_SUCCESS;
 

commit 373a99e489ac0622ac2ed7f37e9670561c5835a8
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Apr 28 12:12:29 2015 +0200

    bus-util: print correct warnings for units that fail but for which we have a NULL result only

diff --git a/src/libsystemd/sd-bus/bus-util.c b/src/libsystemd/sd-bus/bus-util.c
index a84d338..a30493f 100644
--- a/src/libsystemd/sd-bus/bus-util.c
+++ b/src/libsystemd/sd-bus/bus-util.c
@@ -1758,28 +1758,34 @@ static const struct {
 };
 
 static void log_job_error_with_service_result(const char* service, const char *result) {
-        unsigned i;
         _cleanup_free_ char *service_shell_quoted = NULL;
 
         assert(service);
-        assert(result);
 
         service_shell_quoted = shell_maybe_quote(service);
 
-        for (i = 0; i < ELEMENTSOF(explanations); ++i)
-                if (streq(result, explanations[i].result))
-                        break;
+        if (!isempty(result)) {
+                unsigned i;
 
-        if (i < ELEMENTSOF(explanations))
-                log_error("Job for %s failed because %s. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
-                          service,
-                          explanations[i].explanation,
-                          strna(service_shell_quoted));
-        else
-                log_error("Job for %s failed. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
-                          service,
-                          strna(service_shell_quoted));
+                for (i = 0; i < ELEMENTSOF(explanations); ++i)
+                        if (streq(result, explanations[i].result))
+                                break;
+
+                if (i < ELEMENTSOF(explanations)) {
+                        log_error("Job for %s failed because %s. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
+                                  service,
+                                  explanations[i].explanation,
+                                  strna(service_shell_quoted));
 
+                        goto finish;
+                }
+        }
+
+        log_error("Job for %s failed. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
+                  service,
+                  strna(service_shell_quoted));
+
+finish:
         /* For some results maybe additional explanation is required */
         if (streq_ptr(result, "start-limit"))
                 log_info("To force a start use \"systemctl reset-failed %1$s\" followed by \"systemctl start %1$s\" again.",

commit a22e1850c36e52cb9d593b99be59b6ba7639d80a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Apr 28 11:44:24 2015 +0200

    man: clarify that only the first .network file with a matching [Match] matters
    
    http://lists.freedesktop.org/archives/systemd-devel/2015-April/031294.html

diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index c7e4db4..4be9d13 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -91,7 +91,8 @@
       to a given device; and a <literal>[Network]</literal> section
       specifying how the device should be configured. The first (in
       lexical order) of the network files that matches a given device
-      is applied.</para>
+      is applied, all later files are ignored, even if they match as
+      well.</para>
 
       <para>A network file is said to match a device if each of the
       entries in the <literal>[Match]</literal> section matches, or if



More information about the systemd-commits mailing list