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
|
* support the bind/connect/sendmsg cgroup stuff for sandboxing, and possibly
|
||||||
patching around
|
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
|
* chown() tty a service is attached to after the service goes down
|
||||||
|
|
||||||
* optionally: turn on cgroup delegation for per-session scope units
|
* optionally: turn on cgroup delegation for per-session scope units
|
||||||
|
|
|
@ -298,6 +298,7 @@ manpages = [
|
||||||
'sd_bus_release_name_async',
|
'sd_bus_release_name_async',
|
||||||
'sd_bus_request_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_connected_signal', '3', ['sd_bus_get_connected_signal'], ''],
|
||||||
['sd_bus_set_description',
|
['sd_bus_set_description',
|
||||||
'3',
|
'3',
|
||||||
|
|
|
@ -85,6 +85,7 @@
|
||||||
<citerefentry><refentrytitle>sd_bus_set_description</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
<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_sender</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||||
<citerefentry><refentrytitle>sd_bus_set_watch_bind</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_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_destroy_callback</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||||
<citerefentry><refentrytitle>sd_bus_slot_set_floating</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-execute.h"
|
||||||
#include "dbus-job.h"
|
#include "dbus-job.h"
|
||||||
#include "dbus-manager.h"
|
#include "dbus-manager.h"
|
||||||
|
#include "dbus-scope.h"
|
||||||
#include "dbus-unit.h"
|
#include "dbus-unit.h"
|
||||||
#include "dbus.h"
|
#include "dbus.h"
|
||||||
#include "env-util.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);
|
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[] = {
|
const sd_bus_vtable bus_manager_vtable[] = {
|
||||||
SD_BUS_VTABLE_START(0),
|
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("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("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("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("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("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),
|
SD_BUS_METHOD("GetJobBefore", "u", "a(usssoo)", method_get_job_waiting, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include "selinux-access.h"
|
#include "selinux-access.h"
|
||||||
#include "unit.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;
|
Scope *s = userdata;
|
||||||
int r;
|
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("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_PROPERTY("Result", "s", property_get_result, offsetof(Scope, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||||
SD_BUS_SIGNAL("RequestStop", NULL, 0),
|
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
|
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_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);
|
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);
|
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[] = {
|
const sd_bus_vtable bus_unit_vtable[] = {
|
||||||
SD_BUS_VTABLE_START(0),
|
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("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("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("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("Start", "s", "o", method_start, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
SD_BUS_METHOD("Stop", "s", "o", method_stop, 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 */
|
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);
|
unit_add_to_gc_queue(u);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -579,6 +579,9 @@ global:
|
||||||
|
|
||||||
sd_bus_error_move;
|
sd_bus_error_move;
|
||||||
|
|
||||||
|
sd_bus_set_close_on_exit;
|
||||||
|
sd_bus_get_close_on_exit;
|
||||||
|
|
||||||
sd_device_ref;
|
sd_device_ref;
|
||||||
sd_device_unref;
|
sd_device_unref;
|
||||||
|
|
||||||
|
|
|
@ -211,6 +211,7 @@ struct sd_bus {
|
||||||
bool accept_fd:1;
|
bool accept_fd:1;
|
||||||
bool attach_timestamp:1;
|
bool attach_timestamp:1;
|
||||||
bool connected_signal:1;
|
bool connected_signal:1;
|
||||||
|
bool close_on_exit:1;
|
||||||
|
|
||||||
int use_memfd;
|
int use_memfd;
|
||||||
|
|
||||||
|
|
|
@ -232,18 +232,22 @@ _public_ int sd_bus_new(sd_bus **ret) {
|
||||||
|
|
||||||
assert_return(ret, -EINVAL);
|
assert_return(ret, -EINVAL);
|
||||||
|
|
||||||
b = new0(sd_bus, 1);
|
b = new(sd_bus, 1);
|
||||||
if (!b)
|
if (!b)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
b->n_ref = REFCNT_INIT;
|
*b = (sd_bus) {
|
||||||
b->input_fd = b->output_fd = -1;
|
.n_ref = REFCNT_INIT,
|
||||||
b->inotify_fd = -1;
|
.input_fd = -1,
|
||||||
b->message_version = 1;
|
.output_fd = -1,
|
||||||
b->creds_mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME;
|
.inotify_fd = -1,
|
||||||
b->accept_fd = true;
|
.message_version = 1,
|
||||||
b->original_pid = getpid_cached();
|
.creds_mask = SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME,
|
||||||
b->n_groups = (size_t) -1;
|
.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);
|
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);
|
assert(event);
|
||||||
|
|
||||||
|
if (bus->close_on_exit) {
|
||||||
sd_bus_flush(bus);
|
sd_bus_flush(bus);
|
||||||
sd_bus_close(bus);
|
sd_bus_close(bus);
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
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;
|
*ret = bus->method_call_timeout = BUS_DEFAULT_TIMEOUT;
|
||||||
return 0;
|
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) {
|
static int machine_stop_scope(Machine *m) {
|
||||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||||
char *job = NULL;
|
char *job = NULL;
|
||||||
int r;
|
int r, q;
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
assert(m->class != MACHINE_HOST);
|
assert(m->class != MACHINE_HOST);
|
||||||
|
@ -412,10 +412,17 @@ static int machine_stop_scope(Machine *m) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
r = manager_stop_unit(m->manager, m->unit, &error, &job);
|
r = manager_stop_unit(m->manager, m->unit, &error, &job);
|
||||||
if (r < 0)
|
if (r < 0) {
|
||||||
return log_error_errno(r, "Failed to stop machine scope: %s", bus_error_message(&error, r));
|
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) {
|
int machine_stop(Machine *m) {
|
||||||
|
|
|
@ -1363,18 +1363,15 @@ int manager_start_scope(
|
||||||
return r;
|
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)
|
if (r < 0)
|
||||||
return r;
|
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) {
|
if (more_properties) {
|
||||||
r = sd_bus_message_copy(m, more_properties, true);
|
r = sd_bus_message_copy(m, more_properties, true);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -1411,6 +1408,26 @@ int manager_start_scope(
|
||||||
return 1;
|
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) {
|
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;
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||||
int r;
|
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_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_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_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_unit_is_active(Manager *manager, const char *unit);
|
||||||
int manager_job_is_active(Manager *manager, const char *path);
|
int manager_job_is_active(Manager *manager, const char *path);
|
||||||
|
|
|
@ -201,10 +201,11 @@ int register_machine(
|
||||||
return 0;
|
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_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;
|
int r;
|
||||||
|
|
||||||
assert(bus);
|
assert(bus);
|
||||||
|
@ -214,32 +215,11 @@ int terminate_machine(sd_bus *bus, pid_t pid) {
|
||||||
"org.freedesktop.machine1",
|
"org.freedesktop.machine1",
|
||||||
"/org/freedesktop/machine1",
|
"/org/freedesktop/machine1",
|
||||||
"org.freedesktop.machine1.Manager",
|
"org.freedesktop.machine1.Manager",
|
||||||
"GetMachineByPID",
|
"TerminateMachine",
|
||||||
&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",
|
|
||||||
&error,
|
&error,
|
||||||
NULL,
|
NULL,
|
||||||
NULL);
|
"s",
|
||||||
|
machine_name);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_debug("Failed to terminate machine: %s", bus_error_message(&error, r));
|
log_debug("Failed to terminate machine: %s", bus_error_message(&error, r));
|
||||||
|
|
||||||
|
@ -256,9 +236,8 @@ int allocate_scope(
|
||||||
int kill_signal,
|
int kill_signal,
|
||||||
char **properties) {
|
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_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_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
|
||||||
_cleanup_free_ char *scope = NULL;
|
_cleanup_free_ char *scope = NULL;
|
||||||
const char *description, *object;
|
const char *description, *object;
|
||||||
|
@ -295,10 +274,12 @@ int allocate_scope(
|
||||||
|
|
||||||
description = strjoina("Container ", machine_name);
|
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,
|
"PIDs", "au", 1, pid,
|
||||||
"Description", "s", description,
|
"Description", "s", description,
|
||||||
"Delegate", "b", 1,
|
"Delegate", "b", 1,
|
||||||
|
"CollectMode", "s", "inactive-or-failed",
|
||||||
|
"AddRef", "b", 1,
|
||||||
"Slice", "s", isempty(slice) ? SPECIAL_MACHINE_SLICE : slice);
|
"Slice", "s", isempty(slice) ? SPECIAL_MACHINE_SLICE : slice);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return bus_log_create_error(r);
|
return bus_log_create_error(r);
|
||||||
|
@ -345,3 +326,63 @@ int allocate_scope(
|
||||||
|
|
||||||
return 0;
|
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"
|
#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 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 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);
|
r = sd_bus_default_system(&bus);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to open system bus: %m");
|
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) {
|
if (!arg_keep_unit) {
|
||||||
|
@ -4125,8 +4129,12 @@ static int run(int master,
|
||||||
putc('\n', stdout);
|
putc('\n', stdout);
|
||||||
|
|
||||||
/* Kill if it is not dead yet anyway */
|
/* Kill if it is not dead yet anyway */
|
||||||
if (arg_register && !arg_keep_unit && bus)
|
if (bus) {
|
||||||
terminate_machine(bus, *pid);
|
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 */
|
/* Normally redundant, but better safe than sorry */
|
||||||
(void) kill(*pid, SIGKILL);
|
(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_get_allow_interactive_authorization(sd_bus *bus);
|
||||||
int sd_bus_set_exit_on_disconnect(sd_bus *bus, int b);
|
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_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_set_watch_bind(sd_bus *bus, int b);
|
||||||
int sd_bus_get_watch_bind(sd_bus *bus);
|
int sd_bus_get_watch_bind(sd_bus *bus);
|
||||||
int sd_bus_set_connected_signal(sd_bus *bus, int b);
|
int sd_bus_set_connected_signal(sd_bus *bus, int b);
|
||||||
|
|
Loading…
Reference in a new issue