[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