Skip to content

Commit 4c8b6d6

Browse files
committed
sd-event: Mark post sources as pending after dispatching
More post event sources might get added during dispatching, we want to make sure those become pending as well if we're dispatching a non-post event source.
1 parent 6403a81 commit 4c8b6d6

File tree

2 files changed

+66
-11
lines changed

2 files changed

+66
-11
lines changed

src/libsystemd/sd-event/sd-event.c

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4083,6 +4083,22 @@ static int source_memory_pressure_initiate_dispatch(sd_event_source *s) {
40834083
return 0; /* go on, dispatch to user callback */
40844084
}
40854085

4086+
static int mark_post_sources_pending(sd_event *e) {
4087+
sd_event_source *z;
4088+
int r;
4089+
4090+
SET_FOREACH(z, e->post_sources) {
4091+
if (event_source_is_offline(z))
4092+
continue;
4093+
4094+
r = source_set_pending(z, true);
4095+
if (r < 0)
4096+
return r;
4097+
}
4098+
4099+
return 0;
4100+
}
4101+
40864102
static int source_dispatch(sd_event_source *s) {
40874103
EventSourceType saved_type;
40884104
sd_event *saved_event;
@@ -4117,18 +4133,10 @@ static int source_dispatch(sd_event_source *s) {
41174133
}
41184134

41194135
if (s->type != SOURCE_POST) {
4120-
sd_event_source *z;
4121-
41224136
/* If we execute a non-post source, let's mark all post sources as pending. */
4123-
4124-
SET_FOREACH(z, s->event->post_sources) {
4125-
if (event_source_is_offline(z))
4126-
continue;
4127-
4128-
r = source_set_pending(z, true);
4129-
if (r < 0)
4130-
return r;
4131-
}
4137+
r = mark_post_sources_pending(s->event);
4138+
if (r < 0)
4139+
return r;
41324140
}
41334141

41344142
if (s->type == SOURCE_MEMORY_PRESSURE) {
@@ -4237,6 +4245,14 @@ static int source_dispatch(sd_event_source *s) {
42374245

42384246
s->dispatching = false;
42394247

4248+
if (saved_type != SOURCE_POST) {
4249+
/* More post sources might have been added while executing the callback, let's make sure
4250+
* those are marked pending as well. */
4251+
r = mark_post_sources_pending(saved_event);
4252+
if (r < 0)
4253+
return r;
4254+
}
4255+
42404256
finish:
42414257
if (r < 0) {
42424258
log_debug_errno(r, "Event source %s (type %s) returned error, %s: %m",

src/libsystemd/sd-event/test-event.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,4 +946,43 @@ TEST(leave_ratelimit) {
946946
ASSERT_TRUE(manually_left_ratelimit);
947947
}
948948

949+
static int defer_post_handler(sd_event_source *s, void *userdata) {
950+
bool *dispatched_post = ASSERT_PTR(userdata);
951+
952+
*dispatched_post = true;
953+
954+
return 0;
955+
}
956+
957+
static int defer_adds_post_handler(sd_event_source *s, void *userdata) {
958+
sd_event *e = sd_event_source_get_event(s);
959+
960+
/* Add a post event source from within the defer handler */
961+
ASSERT_OK(sd_event_add_post(e, NULL, defer_post_handler, userdata));
962+
963+
return 0;
964+
}
965+
966+
TEST(defer_add_post) {
967+
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
968+
bool dispatched_post = false;
969+
970+
ASSERT_OK(sd_event_default(&e));
971+
972+
/* Add a oneshot defer event source that will add a post event source */
973+
ASSERT_OK(sd_event_add_defer(e, NULL, defer_adds_post_handler, &dispatched_post));
974+
975+
/* Run one iteration - this should dispatch the defer handler */
976+
ASSERT_OK_POSITIVE(sd_event_run(e, UINT64_MAX));
977+
978+
/* The post handler should have been added but not yet dispatched */
979+
ASSERT_FALSE(dispatched_post);
980+
981+
/* Run another iteration - this should dispatch the post handler */
982+
ASSERT_OK_POSITIVE(sd_event_run(e, 0));
983+
984+
/* Now the post handler should have been dispatched */
985+
ASSERT_TRUE(dispatched_post);
986+
}
987+
949988
DEFINE_TEST_MAIN(LOG_DEBUG);

0 commit comments

Comments
 (0)