mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 00:14:32 +09:00
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.
This commit is contained in:
@@ -4083,6 +4083,22 @@ static int source_memory_pressure_initiate_dispatch(sd_event_source *s) {
|
||||
return 0; /* go on, dispatch to user callback */
|
||||
}
|
||||
|
||||
static int mark_post_sources_pending(sd_event *e) {
|
||||
sd_event_source *z;
|
||||
int r;
|
||||
|
||||
SET_FOREACH(z, e->post_sources) {
|
||||
if (event_source_is_offline(z))
|
||||
continue;
|
||||
|
||||
r = source_set_pending(z, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int source_dispatch(sd_event_source *s) {
|
||||
EventSourceType saved_type;
|
||||
sd_event *saved_event;
|
||||
@@ -4117,18 +4133,10 @@ static int source_dispatch(sd_event_source *s) {
|
||||
}
|
||||
|
||||
if (s->type != SOURCE_POST) {
|
||||
sd_event_source *z;
|
||||
|
||||
/* If we execute a non-post source, let's mark all post sources as pending. */
|
||||
|
||||
SET_FOREACH(z, s->event->post_sources) {
|
||||
if (event_source_is_offline(z))
|
||||
continue;
|
||||
|
||||
r = source_set_pending(z, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
r = mark_post_sources_pending(s->event);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (s->type == SOURCE_MEMORY_PRESSURE) {
|
||||
@@ -4237,6 +4245,14 @@ static int source_dispatch(sd_event_source *s) {
|
||||
|
||||
s->dispatching = false;
|
||||
|
||||
if (saved_type != SOURCE_POST) {
|
||||
/* More post sources might have been added while executing the callback, let's make sure
|
||||
* those are marked pending as well. */
|
||||
r = mark_post_sources_pending(saved_event);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
finish:
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Event source %s (type %s) returned error, %s: %m",
|
||||
|
||||
@@ -946,4 +946,43 @@ TEST(leave_ratelimit) {
|
||||
ASSERT_TRUE(manually_left_ratelimit);
|
||||
}
|
||||
|
||||
static int defer_post_handler(sd_event_source *s, void *userdata) {
|
||||
bool *dispatched_post = ASSERT_PTR(userdata);
|
||||
|
||||
*dispatched_post = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int defer_adds_post_handler(sd_event_source *s, void *userdata) {
|
||||
sd_event *e = sd_event_source_get_event(s);
|
||||
|
||||
/* Add a post event source from within the defer handler */
|
||||
ASSERT_OK(sd_event_add_post(e, NULL, defer_post_handler, userdata));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST(defer_add_post) {
|
||||
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
|
||||
bool dispatched_post = false;
|
||||
|
||||
ASSERT_OK(sd_event_default(&e));
|
||||
|
||||
/* Add a oneshot defer event source that will add a post event source */
|
||||
ASSERT_OK(sd_event_add_defer(e, NULL, defer_adds_post_handler, &dispatched_post));
|
||||
|
||||
/* Run one iteration - this should dispatch the defer handler */
|
||||
ASSERT_OK_POSITIVE(sd_event_run(e, UINT64_MAX));
|
||||
|
||||
/* The post handler should have been added but not yet dispatched */
|
||||
ASSERT_FALSE(dispatched_post);
|
||||
|
||||
/* Run another iteration - this should dispatch the post handler */
|
||||
ASSERT_OK_POSITIVE(sd_event_run(e, 0));
|
||||
|
||||
/* Now the post handler should have been dispatched */
|
||||
ASSERT_TRUE(dispatched_post);
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_DEBUG);
|
||||
|
||||
Reference in New Issue
Block a user