|
|
b677e7 |
From 441684c6c961edec1391562fb2f48ff997a6169e Mon Sep 17 00:00:00 2001
|
|
|
b677e7 |
From: Lennart Poettering <lennart@poettering.net>
|
|
|
b677e7 |
Date: Mon, 23 Nov 2020 15:38:00 +0100
|
|
|
b677e7 |
Subject: [PATCH] sd-event: ref event loop while in sd_event_prepare() ot
|
|
|
b677e7 |
sd_event_run()
|
|
|
b677e7 |
|
|
|
b677e7 |
sd_event_prepare() invokes callbacks that might drop the last user ref
|
|
|
b677e7 |
on our event loop. Let's make sure we keep an explicit ref around it, so
|
|
|
b677e7 |
that we won't end up with an invalid pointer. Similar in sd_event_run().
|
|
|
b677e7 |
|
|
|
b677e7 |
Basically, any function that is publically callable that might end up
|
|
|
b677e7 |
invoking callbacks should ref the relevant objects to be protected
|
|
|
b677e7 |
against callbacks destroying these objects while we still want to access
|
|
|
b677e7 |
them. We did this correctly in sd_event_dispatch() and sd_event_loop(),
|
|
|
b677e7 |
but these are not the only ones which are callable from the outside.
|
|
|
b677e7 |
|
|
|
b677e7 |
(cherry picked from commit f814c871e65df8552a055dd887bc94b074037833)
|
|
|
b677e7 |
|
|
|
b677e7 |
Related: #1819868
|
|
|
b677e7 |
---
|
|
|
b677e7 |
src/libsystemd/sd-event/sd-event.c | 15 +++++++++------
|
|
|
b677e7 |
1 file changed, 9 insertions(+), 6 deletions(-)
|
|
|
b677e7 |
|
|
|
b677e7 |
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
|
|
|
b677e7 |
index 537a0b81d4..be1e6e5f53 100644
|
|
|
b677e7 |
--- a/src/libsystemd/sd-event/sd-event.c
|
|
|
b677e7 |
+++ b/src/libsystemd/sd-event/sd-event.c
|
|
|
b677e7 |
@@ -3256,7 +3256,6 @@ static int event_prepare(sd_event *e) {
|
|
|
b677e7 |
|
|
|
b677e7 |
static int dispatch_exit(sd_event *e) {
|
|
|
b677e7 |
sd_event_source *p;
|
|
|
b677e7 |
- _cleanup_(sd_event_unrefp) sd_event *ref = NULL;
|
|
|
b677e7 |
int r;
|
|
|
b677e7 |
|
|
|
b677e7 |
assert(e);
|
|
|
b677e7 |
@@ -3267,7 +3266,7 @@ static int dispatch_exit(sd_event *e) {
|
|
|
b677e7 |
return 0;
|
|
|
b677e7 |
}
|
|
|
b677e7 |
|
|
|
b677e7 |
- ref = sd_event_ref(e);
|
|
|
b677e7 |
+ _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
|
|
|
b677e7 |
e->iteration++;
|
|
|
b677e7 |
e->state = SD_EVENT_EXITING;
|
|
|
b677e7 |
r = source_dispatch(p);
|
|
|
b677e7 |
@@ -3365,6 +3364,9 @@ _public_ int sd_event_prepare(sd_event *e) {
|
|
|
b677e7 |
* syscalls */
|
|
|
b677e7 |
assert_return(!e->default_event_ptr || e->tid == gettid(), -EREMOTEIO);
|
|
|
b677e7 |
|
|
|
b677e7 |
+ /* Make sure that none of the preparation callbacks ends up freeing the event source under our feet */
|
|
|
b677e7 |
+ _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
|
|
|
b677e7 |
+
|
|
|
b677e7 |
if (e->exit_requested)
|
|
|
b677e7 |
goto pending;
|
|
|
b677e7 |
|
|
|
b677e7 |
@@ -3549,9 +3551,8 @@ _public_ int sd_event_dispatch(sd_event *e) {
|
|
|
b677e7 |
|
|
|
b677e7 |
p = event_next_pending(e);
|
|
|
b677e7 |
if (p) {
|
|
|
b677e7 |
- _cleanup_(sd_event_unrefp) sd_event *ref = NULL;
|
|
|
b677e7 |
+ _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
|
|
|
b677e7 |
|
|
|
b677e7 |
- ref = sd_event_ref(e);
|
|
|
b677e7 |
e->state = SD_EVENT_RUNNING;
|
|
|
b677e7 |
r = source_dispatch(p);
|
|
|
b677e7 |
e->state = SD_EVENT_INITIAL;
|
|
|
b677e7 |
@@ -3600,6 +3601,9 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) {
|
|
|
b677e7 |
}
|
|
|
b677e7 |
}
|
|
|
b677e7 |
|
|
|
b677e7 |
+ /* Make sure that none of the preparation callbacks ends up freeing the event source under our feet */
|
|
|
b677e7 |
+ _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
|
|
|
b677e7 |
+
|
|
|
b677e7 |
r = sd_event_prepare(e);
|
|
|
b677e7 |
if (r == 0)
|
|
|
b677e7 |
/* There was nothing? Then wait... */
|
|
|
b677e7 |
@@ -3621,7 +3625,6 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) {
|
|
|
b677e7 |
}
|
|
|
b677e7 |
|
|
|
b677e7 |
_public_ int sd_event_loop(sd_event *e) {
|
|
|
b677e7 |
- _cleanup_(sd_event_unrefp) sd_event *ref = NULL;
|
|
|
b677e7 |
int r;
|
|
|
b677e7 |
|
|
|
b677e7 |
assert_return(e, -EINVAL);
|
|
|
b677e7 |
@@ -3629,7 +3632,7 @@ _public_ int sd_event_loop(sd_event *e) {
|
|
|
b677e7 |
assert_return(!event_pid_changed(e), -ECHILD);
|
|
|
b677e7 |
assert_return(e->state == SD_EVENT_INITIAL, -EBUSY);
|
|
|
b677e7 |
|
|
|
b677e7 |
- ref = sd_event_ref(e);
|
|
|
b677e7 |
+ _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = NULL;
|
|
|
b677e7 |
|
|
|
b677e7 |
while (e->state != SD_EVENT_FINISHED) {
|
|
|
b677e7 |
r = sd_event_run(e, (uint64_t) -1);
|