Merge pull request #10306 from poettering/nspawn-ref-unref
nspawn scope lifecycle fixes
This commit is contained in:
commit
15e9a42074
3
TODO
3
TODO
|
@ -43,6 +43,9 @@ Features:
|
|||
* support the bind/connect/sendmsg cgroup stuff for sandboxing, and possibly
|
||||
patching around
|
||||
|
||||
* maybe implicitly attach monotonic+realtime timestamps to outgoing messages in
|
||||
log.c and sd-journal-send
|
||||
|
||||
* chown() tty a service is attached to after the service goes down
|
||||
|
||||
* optionally: turn on cgroup delegation for per-session scope units
|
||||
|
|
|
@ -298,6 +298,7 @@ manpages = [
|
|||
'sd_bus_release_name_async',
|
||||
'sd_bus_request_name_async'],
|
||||
''],
|
||||
['sd_bus_set_close_on_exit', '3', ['sd_bus_get_close_on_exit'], ''],
|
||||
['sd_bus_set_connected_signal', '3', ['sd_bus_get_connected_signal'], ''],
|
||||
['sd_bus_set_description',
|
||||
'3',
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
<citerefentry><refentrytitle>sd_bus_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_set_sender</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_set_watch_bind</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
<citerefentry><refentrytitle>sd_bus_set_close_on_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
<citerefentry><refentrytitle>sd_bus_slot_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_slot_set_destroy_callback</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_slot_set_floating</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
|
|
105
man/sd_bus_set_close_on_exit.xml
Normal file
105
man/sd_bus_set_close_on_exit.xml
Normal file
|
@ -0,0 +1,105 @@
|
|||
<?xml version='1.0'?>
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: LGPL-2.1+
|
||||
-->
|
||||
|
||||
<refentry id="sd_bus_set_close_on_exit"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
|
||||
<refentryinfo>
|
||||
<title>sd_bus_set_close_on_exit</title>
|
||||
<productname>systemd</productname>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>sd_bus_set_close_on_exit</refentrytitle>
|
||||
<manvolnum>3</manvolnum>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>sd_bus_set_close_on_exit</refname>
|
||||
<refname>sd_bus_get_close_on_exit</refname>
|
||||
|
||||
<refpurpose>Control whether to close the bus connection during the event loop exit phase</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<funcsynopsis>
|
||||
<funcsynopsisinfo>#include <systemd/sd-bus.h></funcsynopsisinfo>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_bus_set_close_on_exit</function></funcdef>
|
||||
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
|
||||
<paramdef>int <parameter>b</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_bus_get_close_on_exit</function></funcdef>
|
||||
<paramdef>sd_bus *<parameter>bus</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para><function>sd_bus_set_close_on_exit()</function> may be used to enable or disable whether the bus connection
|
||||
is automatically flushed (as in
|
||||
<citerefentry><refentrytitle>sd_bus_flush</refentrytitle><manvolnum>3</manvolnum></citerefentry>) and closed (as in
|
||||
<citerefentry><refentrytitle>sd_bus_close</refentrytitle><manvolnum>3</manvolnum></citerefentry>) during the exit
|
||||
phase of the event loop. This logic only applies to bus connections that are attached to an
|
||||
<citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry> event loop, see
|
||||
<citerefentry><refentrytitle>sd_bus_attach_event</refentrytitle><manvolnum>3</manvolnum></citerefentry>. By default
|
||||
this mechanism is enabled and makes sure that any pending messages that have not been written to the bus connection
|
||||
are written out when the event loop is shutting down. In some cases this behaviour is not desirable, for example
|
||||
when the bus connection shall remain usable until after the event loop exited. If <parameter>b</parameter> is
|
||||
true, the feature is enabled (which is the default), otherwise disabled.</para>
|
||||
|
||||
<para><function>sd_bus_get_close_on_exit()</function> may be used to query the current setting of this feature. It
|
||||
returns zero when the feature is disabled, and positive if enabled.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Return Value</title>
|
||||
|
||||
<para>On success, <function>sd_bus_set_close_on_exit()</function> returns 0 or a positive integer. On failure, it returns a negative errno-style
|
||||
error code.</para>
|
||||
|
||||
<para><function>sd_bus_get_close_on_exit()</function> returns 0 if the feature is currently turned off or a
|
||||
positive integer if it is on. On failure, it returns a negative errno-style error code.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Errors</title>
|
||||
|
||||
<para>Returned errors may indicate the following problems:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><constant>-ECHILD</constant></term>
|
||||
|
||||
<listitem><para>The bus connection has been created in a different process.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<xi:include href="libsystemd-pkgconfig.xml" />
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
|
||||
<para>
|
||||
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_flush</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_bus_attach_event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd-event</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_event_add_exit</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
|
@ -12,6 +12,7 @@
|
|||
#include "dbus-execute.h"
|
||||
#include "dbus-job.h"
|
||||
#include "dbus-manager.h"
|
||||
#include "dbus-scope.h"
|
||||
#include "dbus-unit.h"
|
||||
#include "dbus.h"
|
||||
#include "env-util.h"
|
||||
|
@ -2422,6 +2423,29 @@ static int method_get_job_waiting(sd_bus_message *message, void *userdata, sd_bu
|
|||
return bus_job_method_get_waiting_jobs(message, j, error);
|
||||
}
|
||||
|
||||
static int method_abandon_scope(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
Manager *m = userdata;
|
||||
const char *name;
|
||||
Unit *u;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
assert(m);
|
||||
|
||||
r = sd_bus_message_read(message, "s", &name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = bus_get_unit_by_name(m, message, name, &u, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (u->type != UNIT_SCOPE)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit '%s' is not a scope unit, refusing.", name);
|
||||
|
||||
return bus_scope_method_abandon(message, u, error);
|
||||
}
|
||||
|
||||
const sd_bus_vtable bus_manager_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
|
||||
|
@ -2537,6 +2561,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
|
|||
SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("GetUnitProcesses", "s", "a(sus)", method_get_unit_processes, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("AttachProcessesToUnit", "ssau", NULL, method_attach_processes_to_unit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("AbandonScope", "s", NULL, method_abandon_scope, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("GetJob", "u", "o", method_get_job, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("GetJobAfter", "u", "a(usssoo)", method_get_job_waiting, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("GetJobBefore", "u", "a(usssoo)", method_get_job_waiting, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include "selinux-access.h"
|
||||
#include "unit.h"
|
||||
|
||||
static int bus_scope_abandon(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
int bus_scope_method_abandon(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
Scope *s = userdata;
|
||||
int r;
|
||||
|
||||
|
@ -48,7 +48,7 @@ const sd_bus_vtable bus_scope_vtable[] = {
|
|||
SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Scope, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Scope, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_SIGNAL("RequestStop", NULL, 0),
|
||||
SD_BUS_METHOD("Abandon", NULL, NULL, bus_scope_abandon, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("Abandon", NULL, NULL, bus_scope_method_abandon, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_VTABLE_END
|
||||
};
|
||||
|
||||
|
|
|
@ -14,4 +14,6 @@ int bus_scope_commit_properties(Unit *u);
|
|||
|
||||
int bus_scope_send_request_stop(Scope *s);
|
||||
|
||||
int bus_scope_method_abandon(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
|
||||
int bus_scope_track_controller(Scope *s);
|
||||
|
|
|
@ -561,6 +561,44 @@ int bus_unit_method_unref(sd_bus_message *message, void *userdata, sd_bus_error
|
|||
return sd_bus_reply_method_return(message, NULL);
|
||||
}
|
||||
|
||||
static int property_get_refs(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
Unit *u = userdata;
|
||||
const char *i;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
assert(reply);
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "s");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
for (i = sd_bus_track_first(u->bus_track); i; i = sd_bus_track_next(u->bus_track)) {
|
||||
int c, k;
|
||||
|
||||
c = sd_bus_track_count_name(u->bus_track, i);
|
||||
if (c < 0)
|
||||
return c;
|
||||
|
||||
/* Add the item multiple times if the ref count for each is above 1 */
|
||||
for (k = 0; k < c; k++) {
|
||||
r = sd_bus_message_append(reply, "s", i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return sd_bus_message_close_container(reply);
|
||||
}
|
||||
|
||||
const sd_bus_vtable bus_unit_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
|
||||
|
@ -637,6 +675,7 @@ const sd_bus_vtable bus_unit_vtable[] = {
|
|||
SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("InvocationID", "ay", bus_property_get_id128, offsetof(Unit, invocation_id), 0),
|
||||
SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode, offsetof(Unit, collect_mode), 0),
|
||||
SD_BUS_PROPERTY("Refs", "as", property_get_refs, 0, 0),
|
||||
|
||||
SD_BUS_METHOD("Start", "s", "o", method_start, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("Stop", "s", "o", method_stop, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
|
@ -1781,7 +1820,13 @@ static int bus_unit_track_handler(sd_bus_track *t, void *userdata) {
|
|||
|
||||
u->bus_track = sd_bus_track_unref(u->bus_track); /* make sure we aren't called again */
|
||||
|
||||
/* If the client that tracks us disappeared, then there's reason to believe that the cgroup is empty now too,
|
||||
* let's see */
|
||||
unit_add_to_cgroup_empty_queue(u);
|
||||
|
||||
/* Also add the unit to the GC queue, after all if the client left it might be time to GC this unit */
|
||||
unit_add_to_gc_queue(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -579,6 +579,9 @@ global:
|
|||
|
||||
sd_bus_error_move;
|
||||
|
||||
sd_bus_set_close_on_exit;
|
||||
sd_bus_get_close_on_exit;
|
||||
|
||||
sd_device_ref;
|
||||
sd_device_unref;
|
||||
|
||||
|
|
|
@ -211,6 +211,7 @@ struct sd_bus {
|
|||
bool accept_fd:1;
|
||||
bool attach_timestamp:1;
|
||||
bool connected_signal:1;
|
||||
bool close_on_exit:1;
|
||||
|
||||
int use_memfd;
|
||||
|
||||
|
|
|
@ -232,18 +232,22 @@ _public_ int sd_bus_new(sd_bus **ret) {
|
|||
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
b = new0(sd_bus, 1);
|
||||
b = new(sd_bus, 1);
|
||||
if (!b)
|
||||
return -ENOMEM;
|
||||
|
||||
b->n_ref = REFCNT_INIT;
|
||||
b->input_fd = b->output_fd = -1;
|
||||
b->inotify_fd = -1;
|
||||
b->message_version = 1;
|
||||
b->creds_mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME;
|
||||
b->accept_fd = true;
|
||||
b->original_pid = getpid_cached();
|
||||
b->n_groups = (size_t) -1;
|
||||
*b = (sd_bus) {
|
||||
.n_ref = REFCNT_INIT,
|
||||
.input_fd = -1,
|
||||
.output_fd = -1,
|
||||
.inotify_fd = -1,
|
||||
.message_version = 1,
|
||||
.creds_mask = SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME,
|
||||
.accept_fd = true,
|
||||
.original_pid = getpid_cached(),
|
||||
.n_groups = (size_t) -1,
|
||||
.close_on_exit = true,
|
||||
};
|
||||
|
||||
assert_se(pthread_mutex_init(&b->memfd_cache_mutex, NULL) == 0);
|
||||
|
||||
|
@ -3409,8 +3413,10 @@ static int quit_callback(sd_event_source *event, void *userdata) {
|
|||
|
||||
assert(event);
|
||||
|
||||
if (bus->close_on_exit) {
|
||||
sd_bus_flush(bus);
|
||||
sd_bus_close(bus);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -4135,3 +4141,18 @@ _public_ int sd_bus_get_method_call_timeout(sd_bus *bus, uint64_t *ret) {
|
|||
*ret = bus->method_call_timeout = BUS_DEFAULT_TIMEOUT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_bus_set_close_on_exit(sd_bus *bus, int b) {
|
||||
assert_return(bus, -EINVAL);
|
||||
assert_return(bus = bus_resolve(bus), -ENOPKG);
|
||||
|
||||
bus->close_on_exit = b;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_bus_get_close_on_exit(sd_bus *bus) {
|
||||
assert_return(bus, -EINVAL);
|
||||
assert_return(bus = bus_resolve(bus), -ENOPKG);
|
||||
|
||||
return bus->close_on_exit;
|
||||
}
|
||||
|
|
|
@ -403,7 +403,7 @@ int machine_start(Machine *m, sd_bus_message *properties, sd_bus_error *error) {
|
|||
static int machine_stop_scope(Machine *m) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
char *job = NULL;
|
||||
int r;
|
||||
int r, q;
|
||||
|
||||
assert(m);
|
||||
assert(m->class != MACHINE_HOST);
|
||||
|
@ -412,10 +412,17 @@ static int machine_stop_scope(Machine *m) {
|
|||
return 0;
|
||||
|
||||
r = manager_stop_unit(m->manager, m->unit, &error, &job);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to stop machine scope: %s", bus_error_message(&error, r));
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to stop machine scope: %s", bus_error_message(&error, r));
|
||||
sd_bus_error_free(&error);
|
||||
} else
|
||||
free_and_replace(m->scope_job, job);
|
||||
|
||||
return free_and_replace(m->scope_job, job);
|
||||
q = manager_unref_unit(m->manager, m->unit, &error);
|
||||
if (q < 0)
|
||||
log_warning_errno(q, "Failed to drop reference to machine scope, ignoring: %s", bus_error_message(&error, r));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int machine_stop(Machine *m) {
|
||||
|
|
|
@ -1363,18 +1363,15 @@ int manager_start_scope(
|
|||
return r;
|
||||
}
|
||||
|
||||
r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
|
||||
r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)(sv)",
|
||||
"PIDs", "au", 1, pid,
|
||||
"Delegate", "b", 1,
|
||||
"CollectMode", "s", "inactive-or-failed",
|
||||
"AddRef", "b", 1,
|
||||
"TasksMax", "t", UINT64_C(16384));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_append(m, "(sv)", "Delegate", "b", 1);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", UINT64_C(16384));
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
if (more_properties) {
|
||||
r = sd_bus_message_copy(m, more_properties, true);
|
||||
if (r < 0)
|
||||
|
@ -1411,6 +1408,26 @@ int manager_start_scope(
|
|||
return 1;
|
||||
}
|
||||
|
||||
int manager_unref_unit(
|
||||
Manager *m,
|
||||
const char *unit,
|
||||
sd_bus_error *error) {
|
||||
|
||||
assert(m);
|
||||
assert(unit);
|
||||
|
||||
return sd_bus_call_method(
|
||||
m->bus,
|
||||
"org.freedesktop.systemd1",
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"UnrefUnit",
|
||||
error,
|
||||
NULL,
|
||||
"s",
|
||||
unit);
|
||||
}
|
||||
|
||||
int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
int r;
|
||||
|
|
|
@ -50,5 +50,6 @@ int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *err
|
|||
int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, sd_bus_message *more_properties, sd_bus_error *error, char **job);
|
||||
int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
|
||||
int manager_kill_unit(Manager *manager, const char *unit, int signo, sd_bus_error *error);
|
||||
int manager_unref_unit(Manager *m, const char *unit, sd_bus_error *error);
|
||||
int manager_unit_is_active(Manager *manager, const char *unit);
|
||||
int manager_job_is_active(Manager *manager, const char *path);
|
||||
|
|
|
@ -201,10 +201,11 @@ int register_machine(
|
|||
return 0;
|
||||
}
|
||||
|
||||
int terminate_machine(sd_bus *bus, pid_t pid) {
|
||||
int terminate_machine(
|
||||
sd_bus *bus,
|
||||
const char *machine_name) {
|
||||
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
const char *path;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
|
@ -214,32 +215,11 @@ int terminate_machine(sd_bus *bus, pid_t pid) {
|
|||
"org.freedesktop.machine1",
|
||||
"/org/freedesktop/machine1",
|
||||
"org.freedesktop.machine1.Manager",
|
||||
"GetMachineByPID",
|
||||
&error,
|
||||
&reply,
|
||||
"u",
|
||||
(uint32_t) pid);
|
||||
if (r < 0) {
|
||||
/* Note that the machine might already have been
|
||||
* cleaned up automatically, hence don't consider it a
|
||||
* failure if we cannot get the machine object. */
|
||||
log_debug("Failed to get machine: %s", bus_error_message(&error, r));
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_bus_message_read(reply, "o", &path);
|
||||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
|
||||
r = sd_bus_call_method(
|
||||
bus,
|
||||
"org.freedesktop.machine1",
|
||||
path,
|
||||
"org.freedesktop.machine1.Machine",
|
||||
"Terminate",
|
||||
"TerminateMachine",
|
||||
&error,
|
||||
NULL,
|
||||
NULL);
|
||||
"s",
|
||||
machine_name);
|
||||
if (r < 0)
|
||||
log_debug("Failed to terminate machine: %s", bus_error_message(&error, r));
|
||||
|
||||
|
@ -256,9 +236,8 @@ int allocate_scope(
|
|||
int kill_signal,
|
||||
char **properties) {
|
||||
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
_cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
|
||||
_cleanup_free_ char *scope = NULL;
|
||||
const char *description, *object;
|
||||
|
@ -295,10 +274,12 @@ int allocate_scope(
|
|||
|
||||
description = strjoina("Container ", machine_name);
|
||||
|
||||
r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)",
|
||||
r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)(sv)(sv)",
|
||||
"PIDs", "au", 1, pid,
|
||||
"Description", "s", description,
|
||||
"Delegate", "b", 1,
|
||||
"CollectMode", "s", "inactive-or-failed",
|
||||
"AddRef", "b", 1,
|
||||
"Slice", "s", isempty(slice) ? SPECIAL_MACHINE_SLICE : slice);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
@ -345,3 +326,63 @@ int allocate_scope(
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int terminate_scope(
|
||||
sd_bus *bus,
|
||||
const char *machine_name) {
|
||||
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_free_ char *scope = NULL;
|
||||
int r;
|
||||
|
||||
r = unit_name_mangle_with_suffix(machine_name, 0, ".scope", &scope);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to mangle scope name: %m");
|
||||
|
||||
r = sd_bus_call_method(
|
||||
bus,
|
||||
"org.freedesktop.systemd1",
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"AbandonScope",
|
||||
&error,
|
||||
NULL,
|
||||
"s",
|
||||
scope);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to abandon scope '%s', ignoring: %s", scope, bus_error_message(&error, r));
|
||||
sd_bus_error_free(&error);
|
||||
}
|
||||
|
||||
r = sd_bus_call_method(
|
||||
bus,
|
||||
"org.freedesktop.systemd1",
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"KillUnit",
|
||||
&error,
|
||||
NULL,
|
||||
"ssi",
|
||||
scope,
|
||||
"all",
|
||||
(int32_t) SIGKILL);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to SIGKILL scope '%s', ignoring: %s", scope, bus_error_message(&error, r));
|
||||
sd_bus_error_free(&error);
|
||||
}
|
||||
|
||||
r = sd_bus_call_method(
|
||||
bus,
|
||||
"org.freedesktop.systemd1",
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"UnrefUnit",
|
||||
&error,
|
||||
NULL,
|
||||
"s",
|
||||
scope);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to drop reference to scope '%s', ignoring: %s", scope, bus_error_message(&error, r));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "nspawn-mount.h"
|
||||
|
||||
int register_machine(sd_bus *bus, const char *machine_name, pid_t pid, const char *directory, sd_id128_t uuid, int local_ifindex, const char *slice, CustomMount *mounts, unsigned n_mounts, int kill_signal, char **properties, bool keep_unit, const char *service);
|
||||
int terminate_machine(sd_bus *bus, pid_t pid);
|
||||
int terminate_machine(sd_bus *bus, const char *machine_name);
|
||||
|
||||
int allocate_scope(sd_bus *bus, const char *machine_name, pid_t pid, const char *slice, CustomMount *mounts, unsigned n_mounts, int kill_signal, char **properties);
|
||||
int terminate_scope(sd_bus *bus, const char *machine_name);
|
||||
|
|
|
@ -3974,6 +3974,10 @@ static int run(int master,
|
|||
r = sd_bus_default_system(&bus);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to open system bus: %m");
|
||||
|
||||
r = sd_bus_set_close_on_exit(bus, false);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to disable close-on-exit behaviour: %m");
|
||||
}
|
||||
|
||||
if (!arg_keep_unit) {
|
||||
|
@ -4125,8 +4129,12 @@ static int run(int master,
|
|||
putc('\n', stdout);
|
||||
|
||||
/* Kill if it is not dead yet anyway */
|
||||
if (arg_register && !arg_keep_unit && bus)
|
||||
terminate_machine(bus, *pid);
|
||||
if (bus) {
|
||||
if (arg_register)
|
||||
terminate_machine(bus, arg_machine);
|
||||
else if (!arg_keep_unit)
|
||||
terminate_scope(bus, arg_machine);
|
||||
}
|
||||
|
||||
/* Normally redundant, but better safe than sorry */
|
||||
(void) kill(*pid, SIGKILL);
|
||||
|
|
|
@ -154,6 +154,8 @@ int sd_bus_set_allow_interactive_authorization(sd_bus *bus, int b);
|
|||
int sd_bus_get_allow_interactive_authorization(sd_bus *bus);
|
||||
int sd_bus_set_exit_on_disconnect(sd_bus *bus, int b);
|
||||
int sd_bus_get_exit_on_disconnect(sd_bus *bus);
|
||||
int sd_bus_set_close_on_exit(sd_bus *bus, int b);
|
||||
int sd_bus_get_close_on_exit(sd_bus *bus);
|
||||
int sd_bus_set_watch_bind(sd_bus *bus, int b);
|
||||
int sd_bus_get_watch_bind(sd_bus *bus);
|
||||
int sd_bus_set_connected_signal(sd_bus *bus, int b);
|
||||
|
|
Loading…
Reference in a new issue