dryang / rpms / systemd

Forked from rpms/systemd a year ago
Clone
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);