From 064b9b2bb3544707171662f548677259c3d6aa7f Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 20 Jul 2025 02:12:00 +0900 Subject: [PATCH 1/2] sd-event: drop inotify event from buffer when no event source is triggered Even when we receive an inotify event, there is no relevant event source exists. In that case, we need to drop the event from the buffer, otherwise we cannot escape from the loop. Fixes #38265. --- src/libsystemd/sd-event/sd-event.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index 8ed10c9f8e..869747e929 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -3955,9 +3955,12 @@ static int event_inotify_data_process(sd_event *e, InotifyData *d) { } } - /* Something pending now? If so, let's finish, otherwise let's read more. */ + /* Something pending now? If so, let's finish. */ if (d->n_pending > 0) return 1; + + /* otherwise, drop the event and let's read more */ + event_inotify_data_drop(e, d, sz); } return 0; From b92258eb229f84680b91e744e98d72429710770e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 20 Jul 2025 01:27:10 +0900 Subject: [PATCH 2/2] test: add test case for issue #38265 --- src/libsystemd/sd-event/test-event.c | 34 ++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/libsystemd/sd-event/test-event.c b/src/libsystemd/sd-event/test-event.c index 23a45c7276..a61b64a85a 100644 --- a/src/libsystemd/sd-event/test-event.c +++ b/src/libsystemd/sd-event/test-event.c @@ -806,6 +806,40 @@ TEST(inotify_process_buffered_data) { assert_se(sd_event_wait(e, 0) == 0); } +static int inotify_handler_issue_38265(sd_event_source *s, const struct inotify_event *event, void *userdata) { + log_debug("Inotify event: mask=0x%x name=%s", event->mask, event->name); + return 0; +} + +TEST(inotify_issue_38265) { + _cleanup_(rm_rf_physical_and_freep) char *t = NULL; + _cleanup_(sd_event_source_unrefp) sd_event_source *a = NULL, *b = NULL; + _cleanup_(sd_event_unrefp) sd_event *e = NULL; + _cleanup_free_ char *p = NULL; + + /* For issue #38265. */ + + ASSERT_OK(mkdtemp_malloc("/tmp/test-inotify-XXXXXX", &t)); + + ASSERT_OK(sd_event_default(&e)); + + /* Create inode data that watches IN_MODIFY */ + ASSERT_OK(sd_event_add_inotify(e, &a, t, IN_CREATE | IN_MODIFY, inotify_handler_issue_38265, NULL)); + ASSERT_OK(sd_event_add_inotify(e, &b, t, IN_CREATE, inotify_handler_issue_38265, NULL)); + + /* Then drop the event source that is interested in IN_MODIFY */ + ASSERT_NULL(a = sd_event_source_unref(a)); + + /* Trigger IN_MODIFY (of course with IN_CREATE) */ + ASSERT_NOT_NULL(p = path_join(t, "hoge")); + ASSERT_OK(write_string_file(p, "aaa", WRITE_STRING_FILE_CREATE)); + + for (unsigned i = 1; i < 5; i++) { + log_debug("Running event loop cycle %u to process inotify events...", i); + ASSERT_OK(sd_event_run(e, USEC_PER_MSEC)); + } +} + TEST(fork) { _cleanup_(sd_event_unrefp) sd_event *e = NULL; int r;