Skip to content

Commit 2d4a39e

Browse files
committed
core: introduce new stop protocol for unit scopes
By specifiy a Controller property when creating the scope a client can specify a bus name that will be notified with a RequestStop bus signal when the scope has been asked to shut down, instead of sending SIGTERM to the scope processes themselves. https://bugzilla.redhat.com/show_bug.cgi?id=1032695
1 parent fb818b2 commit 2d4a39e

File tree

5 files changed

+86
-7
lines changed

5 files changed

+86
-7
lines changed

src/core/dbus-scope.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,16 @@
2626
#include "dbus-kill.h"
2727
#include "dbus-scope.h"
2828
#include "bus-util.h"
29+
#include "bus-internal.h"
2930

3031
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, scope_result, ScopeResult);
3132

3233
const sd_bus_vtable bus_scope_vtable[] = {
3334
SD_BUS_VTABLE_START(0),
35+
SD_BUS_PROPERTY("Controller", "s", NULL, offsetof(Scope, controller), SD_BUS_VTABLE_PROPERTY_CONST),
3436
SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Scope, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
3537
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Scope, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
38+
SD_BUS_SIGNAL("RequestStop", NULL, 0),
3639
SD_BUS_VTABLE_END
3740
};
3841

@@ -86,6 +89,32 @@ static int bus_scope_set_transient_property(
8689

8790
return 1;
8891

92+
} else if (streq(name, "Controller")) {
93+
const char *controller;
94+
char *c;
95+
96+
r = sd_bus_message_read(message, "s", &controller);
97+
if (r < 0)
98+
return r;
99+
100+
if (!isempty(controller) && !service_name_is_valid(controller))
101+
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Controller '%s' is not a valid bus name.", controller);
102+
103+
if (mode != UNIT_CHECK) {
104+
if (isempty(controller))
105+
c = NULL;
106+
else {
107+
c = strdup(controller);
108+
if (!c)
109+
return -ENOMEM;
110+
}
111+
112+
free(s->controller);
113+
s->controller = c;
114+
}
115+
116+
return 1;
117+
89118
} else if (streq(name, "TimeoutStopUSec")) {
90119

91120
if (mode != UNIT_CHECK) {
@@ -145,3 +174,29 @@ int bus_scope_commit_properties(Unit *u) {
145174
unit_realize_cgroup(u);
146175
return 0;
147176
}
177+
178+
int bus_scope_send_request_stop(Scope *s) {
179+
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
180+
_cleanup_free_ char *p = NULL;
181+
int r;
182+
183+
assert(s);
184+
185+
if (!s->controller)
186+
return 0;
187+
188+
p = unit_dbus_path(UNIT(s));
189+
if (!p)
190+
return -ENOMEM;
191+
192+
r = sd_bus_message_new_signal(
193+
UNIT(s)->manager->api_bus,
194+
p,
195+
"org.freedesktop.systemd1.Scope",
196+
"RequestStop",
197+
&m);
198+
if (r < 0)
199+
return r;
200+
201+
return sd_bus_send_to(UNIT(s)->manager->api_bus, m, /* s->controller */ NULL, NULL);
202+
}

src/core/dbus-scope.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,5 @@ extern const sd_bus_vtable bus_scope_vtable[];
2828

2929
int bus_scope_set_property(Unit *u, const char *name, sd_bus_message *i, UnitSetPropertiesMode mode, sd_bus_error *error);
3030
int bus_scope_commit_properties(Unit *u);
31+
32+
int bus_scope_send_request_stop(Scope *s);

src/core/scope.c

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ static void scope_done(Unit *u) {
6464

6565
cgroup_context_done(&s->cgroup_context);
6666

67+
free(s->controller);
68+
6769
set_free(s->pids);
6870
s->pids = NULL;
6971

@@ -217,20 +219,30 @@ static void scope_enter_dead(Scope *s, ScopeResult f) {
217219
}
218220

219221
static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
222+
bool skip_signal = false;
220223
int r;
221224

222225
assert(s);
223226

224227
if (f != SCOPE_SUCCESS)
225228
s->result = f;
226229

227-
r = unit_kill_context(
228-
UNIT(s),
229-
&s->kill_context,
230-
state != SCOPE_STOP_SIGTERM,
231-
-1, -1, false);
232-
if (r < 0)
233-
goto fail;
230+
/* If we have a controller set let's ask the controller nicely
231+
* to terminate the scope, instead of us going directly into
232+
* SIGTERM beserk mode */
233+
if (state == SCOPE_STOP_SIGTERM)
234+
skip_signal = bus_scope_send_request_stop(s) > 0;
235+
236+
if (!skip_signal) {
237+
r = unit_kill_context(
238+
UNIT(s),
239+
&s->kill_context,
240+
state != SCOPE_STOP_SIGTERM,
241+
-1, -1, false);
242+
if (r < 0)
243+
goto fail;
244+
} else
245+
r = 1;
234246

235247
if (r > 0) {
236248
r = scope_arm_timer(s);

src/core/scope.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ struct Scope {
5555

5656
usec_t timeout_stop_usec;
5757

58+
char *controller;
59+
5860
Set *pids;
5961

6062
sd_event_source *timer_event_source;

src/run/run.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,14 @@ static int start_transient_scope(
356356
if (r < 0)
357357
return r;
358358

359+
{
360+
const char *unique_id;
361+
sd_bus_get_unique_name(bus, &unique_id);
362+
r = sd_bus_message_append(m, "(sv)", "Controller", "s", unique_id);
363+
if (r < 0)
364+
return r;
365+
}
366+
359367
r = message_start_transient_unit_send(bus, m, error, NULL);
360368
if (r < 0)
361369
return r;

0 commit comments

Comments
 (0)