From 32861b4c763d8d228e4980cda32e51706dd9e081 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 26 Jun 2022 06:41:33 +0900 Subject: [PATCH 1/3] sd-event: use LIST_IS_EMPTY() --- src/libsystemd/sd-event/sd-event.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index e5d370d4f3..78b4351c2a 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -1799,7 +1799,7 @@ static void event_free_inode_data( if (!d) return; - assert(!d->event_sources); + assert(LIST_IS_EMPTY(d->event_sources)); if (d->fd >= 0) { LIST_REMOVE(to_close, e->inode_data_to_close, d); @@ -1862,7 +1862,7 @@ static void event_gc_inode_data( if (!d) return; - if (d->event_sources) + if (!LIST_IS_EMPTY(d->event_sources)) return; inotify_data = d->inotify_data; @@ -3954,7 +3954,7 @@ static int process_epoll(sd_event *e, usec_t timeout, int64_t threshold, int64_t n_event_max = MALLOC_ELEMENTSOF(e->event_queue); /* If we still have inotify data buffered, then query the other fds, but don't wait on it */ - if (e->inotify_data_buffered) + if (!LIST_IS_EMPTY(e->inotify_data_buffered)) timeout = 0; for (;;) { From 067fc917026fd1fe601de0198c5ea7b3ba782d1e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 26 Jun 2022 06:42:22 +0900 Subject: [PATCH 2/3] sd-event: make sd_event_prepare() return positive when buffered inotify data exists Previously, even if there is buffered inotify data, sd_event_prepare() did not process the data when there is no pending event source. Fixes #23826. --- src/libsystemd/sd-event/sd-event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index 78b4351c2a..a37147d1d5 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -3874,7 +3874,7 @@ _public_ int sd_event_prepare(sd_event *e) { event_close_inode_data_fds(e); - if (event_next_pending(e) || e->need_process_child) + if (event_next_pending(e) || e->need_process_child || !LIST_IS_EMPTY(e->inotify_data_buffered)) goto pending; e->state = SD_EVENT_ARMED; From c7b5a5a7360984df4524ffac5e443e12814448d5 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 28 Jun 2022 00:03:51 +0900 Subject: [PATCH 3/3] test: add another test for inotify event source The test case is for issue #23826. --- src/libsystemd/sd-event/test-event.c | 52 ++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/libsystemd/sd-event/test-event.c b/src/libsystemd/sd-event/test-event.c index ea29def3d5..cc3b84cf46 100644 --- a/src/libsystemd/sd-event/test-event.c +++ b/src/libsystemd/sd-event/test-event.c @@ -757,4 +757,56 @@ TEST(inotify_self_destroy) { assert_se(sd_event_loop(e) >= 0); } +struct inotify_process_buffered_data_context { + const char *path[2]; + unsigned i; +}; + +static int inotify_process_buffered_data_handler(sd_event_source *s, const struct inotify_event *ev, void *userdata) { + struct inotify_process_buffered_data_context *c = ASSERT_PTR(userdata); + const char *description; + + assert_se(sd_event_source_get_description(s, &description) >= 0); + + assert_se(c->i < 2); + assert_se(streq(c->path[c->i], description)); + c->i++; + + return 1; +} + +TEST(inotify_process_buffered_data) { + _cleanup_(rm_rf_physical_and_freep) char *p = NULL, *q = NULL; + _cleanup_(sd_event_source_unrefp) sd_event_source *a = NULL, *b = NULL; + _cleanup_(sd_event_unrefp) sd_event *e = NULL; + _cleanup_free_ char *z = NULL; + + /* For issue #23826 */ + + assert_se(sd_event_default(&e) >= 0); + + assert_se(mkdtemp_malloc("/tmp/test-inotify-XXXXXX", &p) >= 0); + assert_se(mkdtemp_malloc("/tmp/test-inotify-XXXXXX", &q) >= 0); + + struct inotify_process_buffered_data_context context = { + .path = { p, q }, + }; + + assert_se(sd_event_add_inotify(e, &a, p, IN_CREATE, inotify_process_buffered_data_handler, &context) >= 0); + assert_se(sd_event_add_inotify(e, &b, q, IN_CREATE, inotify_process_buffered_data_handler, &context) >= 0); + + assert_se(z = path_join(p, "aaa")); + assert_se(touch(z) >= 0); + z = mfree(z); + assert_se(z = path_join(q, "bbb")); + assert_se(touch(z) >= 0); + z = mfree(z); + + assert_se(sd_event_run(e, 10 * USEC_PER_SEC) > 0); + assert_se(sd_event_prepare(e) > 0); /* issue #23826: this was 0. */ + assert_se(sd_event_dispatch(e) > 0); + assert_se(sd_event_prepare(e) == 0); + assert_se(sd_event_wait(e, 0) == 0); +} + DEFINE_TEST_MAIN(LOG_DEBUG);