diff options
Diffstat (limited to 'src/libsystemd/sd-event')
-rw-r--r-- | src/libsystemd/sd-event/event-source.h | 3 | ||||
-rw-r--r-- | src/libsystemd/sd-event/event-util.c | 26 | ||||
-rw-r--r-- | src/libsystemd/sd-event/event-util.h | 6 | ||||
-rw-r--r-- | src/libsystemd/sd-event/sd-event.c | 62 | ||||
-rw-r--r-- | src/libsystemd/sd-event/test-event.c | 48 |
5 files changed, 117 insertions, 28 deletions
diff --git a/src/libsystemd/sd-event/event-source.h b/src/libsystemd/sd-event/event-source.h index f4e38d7..d05bcf0 100644 --- a/src/libsystemd/sd-event/event-source.h +++ b/src/libsystemd/sd-event/event-source.h @@ -189,6 +189,9 @@ struct inode_data { * iteration. */ int fd; + /* The path that the fd points to. The field is optional. */ + char *path; + /* The inotify "watch descriptor" */ int wd; diff --git a/src/libsystemd/sd-event/event-util.c b/src/libsystemd/sd-event/event-util.c index a310122..862455e 100644 --- a/src/libsystemd/sd-event/event-util.c +++ b/src/libsystemd/sd-event/event-util.c @@ -151,3 +151,29 @@ int event_add_time_change(sd_event *e, sd_event_source **ret, sd_event_io_handle return 0; } + +int event_add_child_pidref( + sd_event *e, + sd_event_source **s, + const PidRef *pid, + int options, + sd_event_child_handler_t callback, + void *userdata) { + + if (!pidref_is_set(pid)) + return -ESRCH; + + if (pid->fd >= 0) + return sd_event_add_child_pidfd(e, s, pid->fd, options, callback, userdata); + + return sd_event_add_child(e, s, pid->pid, options, callback, userdata); +} + +dual_timestamp* event_dual_timestamp_now(sd_event *e, dual_timestamp *ts) { + assert(e); + assert(ts); + + assert_se(sd_event_now(e, CLOCK_REALTIME, &ts->realtime) >= 0); + assert_se(sd_event_now(e, CLOCK_MONOTONIC, &ts->monotonic) >= 0); + return ts; +} diff --git a/src/libsystemd/sd-event/event-util.h b/src/libsystemd/sd-event/event-util.h index c185584..7002ca3 100644 --- a/src/libsystemd/sd-event/event-util.h +++ b/src/libsystemd/sd-event/event-util.h @@ -5,6 +5,8 @@ #include "sd-event.h" +#include "pidref.h" + int event_reset_time( sd_event *e, sd_event_source **s, @@ -32,3 +34,7 @@ static inline int event_source_disable(sd_event_source *s) { } int event_add_time_change(sd_event *e, sd_event_source **ret, sd_event_io_handler_t callback, void *userdata); + +int event_add_child_pidref(sd_event *e, sd_event_source **s, const PidRef *pid, int options, sd_event_child_handler_t callback, void *userdata); + +dual_timestamp* event_dual_timestamp_now(sd_event *e, dual_timestamp *ts); diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c index b6899df..a1305ef 100644 --- a/src/libsystemd/sd-event/sd-event.c +++ b/src/libsystemd/sd-event/sd-event.c @@ -1,6 +1,9 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include <sys/epoll.h> +#if HAVE_PIDFD_OPEN +#include <sys/pidfd.h> +#endif #include <sys/timerfd.h> #include <sys/wait.h> @@ -1165,10 +1168,10 @@ static int source_set_pending(sd_event_source *s, bool b) { assert(s->inotify.inode_data->inotify_data); if (b) - s->inotify.inode_data->inotify_data->n_pending ++; + s->inotify.inode_data->inotify_data->n_pending++; else { assert(s->inotify.inode_data->inotify_data->n_pending > 0); - s->inotify.inode_data->inotify_data->n_pending --; + s->inotify.inode_data->inotify_data->n_pending--; } } @@ -1574,7 +1577,7 @@ static int child_exit_callback(sd_event_source *s, const siginfo_t *si, void *us static bool shall_use_pidfd(void) { /* Mostly relevant for debugging, i.e. this is used in test-event.c to test the event loop once with and once without pidfd */ - return getenv_bool_secure("SYSTEMD_PIDFD") != 0; + return secure_getenv_bool("SYSTEMD_PIDFD") != 0; } _public_ int sd_event_add_child( @@ -1976,7 +1979,7 @@ _public_ int sd_event_add_memory_pressure( env = secure_getenv("MEMORY_PRESSURE_WRITE"); if (env) { - r = unbase64mem(env, SIZE_MAX, &write_buffer, &write_buffer_size); + r = unbase64mem(env, &write_buffer, &write_buffer_size); if (r < 0) return r; } @@ -2231,8 +2234,8 @@ static int inode_data_compare(const struct inode_data *x, const struct inode_dat static void inode_data_hash_func(const struct inode_data *d, struct siphash *state) { assert(d); - siphash24_compress(&d->dev, sizeof(d->dev), state); - siphash24_compress(&d->ino, sizeof(d->ino), state); + siphash24_compress_typesafe(d->dev, state); + siphash24_compress_typesafe(d->ino, state); } DEFINE_PRIVATE_HASH_OPS(inode_data_hash_ops, struct inode_data, inode_data_hash_func, inode_data_compare); @@ -2272,6 +2275,7 @@ static void event_free_inode_data( assert_se(hashmap_remove(d->inotify_data->inodes, d) == d); } + free(d->path); free(d); } @@ -2512,6 +2516,15 @@ static int event_add_inotify_fd_internal( } LIST_PREPEND(to_close, e->inode_data_to_close_list, inode_data); + + _cleanup_free_ char *path = NULL; + r = fd_get_path(inode_data->fd, &path); + if (r < 0 && r != -ENOSYS) { /* The path is optional, hence ignore -ENOSYS. */ + event_gc_inode_data(e, inode_data); + return r; + } + + free_and_replace(inode_data->path, path); } /* Link our event source to the inode data object */ @@ -2797,6 +2810,13 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority) } LIST_PREPEND(to_close, s->event->inode_data_to_close_list, new_inode_data); + + _cleanup_free_ char *path = NULL; + r = fd_get_path(new_inode_data->fd, &path); + if (r < 0 && r != -ENOSYS) + goto fail; + + free_and_replace(new_inode_data->path, path); } /* Move the event source to the new inode data structure */ @@ -3281,13 +3301,29 @@ _public_ int sd_event_source_set_child_process_own(sd_event_source *s, int own) return 0; } -_public_ int sd_event_source_get_inotify_mask(sd_event_source *s, uint32_t *mask) { +_public_ int sd_event_source_get_inotify_mask(sd_event_source *s, uint32_t *ret) { assert_return(s, -EINVAL); - assert_return(mask, -EINVAL); + assert_return(ret, -EINVAL); assert_return(s->type == SOURCE_INOTIFY, -EDOM); assert_return(!event_origin_changed(s->event), -ECHILD); - *mask = s->inotify.mask; + *ret = s->inotify.mask; + return 0; +} + +_public_ int sd_event_source_get_inotify_path(sd_event_source *s, const char **ret) { + assert_return(s, -EINVAL); + assert_return(ret, -EINVAL); + assert_return(s->type == SOURCE_INOTIFY, -EDOM); + assert_return(!event_origin_changed(s->event), -ECHILD); + + if (!s->inotify.inode_data) + return -ESTALE; /* already disconnected. */ + + if (!s->inotify.inode_data->path) + return -ENOSYS; /* /proc was not mounted? */ + + *ret = s->inotify.inode_data->path; return 0; } @@ -3999,7 +4035,7 @@ static int process_inotify(sd_event *e) { if (r < 0) return r; if (r > 0) - done ++; + done++; } return done; @@ -4914,13 +4950,13 @@ _public_ int sd_event_get_state(sd_event *e) { _public_ int sd_event_get_exit_code(sd_event *e, int *code) { assert_return(e, -EINVAL); assert_return(e = event_resolve(e), -ENOPKG); - assert_return(code, -EINVAL); assert_return(!event_origin_changed(e), -ECHILD); if (!e->exit_requested) return -ENODATA; - *code = e->exit_code; + if (code) + *code = e->exit_code; return 0; } @@ -5037,7 +5073,7 @@ _public_ int sd_event_set_watchdog(sd_event *e, int b) { } } - e->watchdog = !!b; + e->watchdog = b; return e->watchdog; fail: diff --git a/src/libsystemd/sd-event/test-event.c b/src/libsystemd/sd-event/test-event.c index cc3d84e..57dee39 100644 --- a/src/libsystemd/sd-event/test-event.c +++ b/src/libsystemd/sd-event/test-event.c @@ -1,5 +1,8 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#if HAVE_PIDFD_OPEN +#include <sys/pidfd.h> +#endif #include <sys/wait.h> #include <unistd.h> @@ -92,7 +95,7 @@ static int signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, assert_se(userdata == INT_TO_PTR('e')); - assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGUSR2, -1) >= 0); + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, SIGUSR2) >= 0); pid = fork(); assert_se(pid >= 0); @@ -142,7 +145,7 @@ static int defer_handler(sd_event_source *s, void *userdata) { assert_se(userdata == INT_TO_PTR('d')); - assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGUSR1, -1) >= 0); + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGUSR1) >= 0); assert_se(sd_event_add_signal(sd_event_source_get_event(s), &p, SIGUSR1, signal_handler, INT_TO_PTR('e')) >= 0); assert_se(sd_event_source_set_enabled(p, SD_EVENT_ONESHOT) >= 0); @@ -254,7 +257,7 @@ static void test_basic_one(bool with_pidfd) { assert_se(sd_event_source_set_prepare(z, prepare_handler) >= 0); /* Test for floating event sources */ - assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+1, -1) >= 0); + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+1) >= 0); assert_se(sd_event_add_signal(e, NULL, SIGRTMIN+1, NULL, NULL) >= 0); assert_se(write(a[1], &ch, 1) >= 0); @@ -346,7 +349,7 @@ TEST(rtqueue) { assert_se(sd_event_default(&e) >= 0); - assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+2, SIGRTMIN+3, SIGUSR2, -1) >= 0); + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGRTMIN+2, SIGRTMIN+3, SIGUSR2) >= 0); assert_se(sd_event_add_signal(e, &u, SIGRTMIN+2, rtqueue_handler, NULL) >= 0); assert_se(sd_event_add_signal(e, &v, SIGRTMIN+3, rtqueue_handler, NULL) >= 0); assert_se(sd_event_add_signal(e, &s, SIGUSR2, rtqueue_handler, NULL) >= 0); @@ -396,6 +399,7 @@ struct inotify_context { unsigned create_called[CREATE_EVENTS_MAX]; unsigned create_overflow; unsigned n_create_events; + const char *path; }; static void maybe_exit(sd_event_source *s, struct inotify_context *c) { @@ -422,10 +426,12 @@ static void maybe_exit(sd_event_source *s, struct inotify_context *c) { } static int inotify_handler(sd_event_source *s, const struct inotify_event *ev, void *userdata) { - struct inotify_context *c = userdata; - const char *description; + struct inotify_context *c = ASSERT_PTR(userdata); + const char *path, *description; unsigned bit, n; + assert_se(sd_event_source_get_inotify_path(s, &path) >= 0); + assert_se(sd_event_source_get_description(s, &description) >= 0); assert_se(safe_atou(description, &n) >= 0); @@ -433,11 +439,12 @@ static int inotify_handler(sd_event_source *s, const struct inotify_event *ev, v bit = 1U << n; if (ev->mask & IN_Q_OVERFLOW) { - log_info("inotify-handler <%s>: overflow", description); + log_info("inotify-handler for %s <%s>: overflow", path, description); c->create_overflow |= bit; } else if (ev->mask & IN_CREATE) { + assert_se(path_equal_or_inode_same(path, c->path, 0)); if (streq(ev->name, "sub")) - log_debug("inotify-handler <%s>: create on %s", description, ev->name); + log_debug("inotify-handler for %s <%s>: create on %s", path, description, ev->name); else { unsigned i; @@ -446,7 +453,7 @@ static int inotify_handler(sd_event_source *s, const struct inotify_event *ev, v c->create_called[i] |= bit; } } else if (ev->mask & IN_DELETE) { - log_info("inotify-handler <%s>: delete of %s", description, ev->name); + log_info("inotify-handler for %s <%s>: delete of %s", path, description, ev->name); assert_se(streq(ev->name, "sub")); } else assert_not_reached(); @@ -456,16 +463,19 @@ static int inotify_handler(sd_event_source *s, const struct inotify_event *ev, v } static int delete_self_handler(sd_event_source *s, const struct inotify_event *ev, void *userdata) { - struct inotify_context *c = userdata; + struct inotify_context *c = ASSERT_PTR(userdata); + const char *path; + + assert_se(sd_event_source_get_inotify_path(s, &path) >= 0); if (ev->mask & IN_Q_OVERFLOW) { - log_info("delete-self-handler: overflow"); + log_info("delete-self-handler for %s: overflow", path); c->delete_self_handler_called = true; } else if (ev->mask & IN_DELETE_SELF) { - log_info("delete-self-handler: delete-self"); + log_info("delete-self-handler for %s: delete-self", path); c->delete_self_handler_called = true; } else if (ev->mask & IN_IGNORED) { - log_info("delete-self-handler: ignore"); + log_info("delete-self-handler for %s: ignore", path); } else assert_not_reached(); @@ -480,7 +490,7 @@ static void test_inotify_one(unsigned n_create_events) { .n_create_events = n_create_events, }; sd_event *e = NULL; - const char *q; + const char *q, *pp; unsigned i; log_info("/* %s(%u) */", __func__, n_create_events); @@ -488,6 +498,7 @@ static void test_inotify_one(unsigned n_create_events) { assert_se(sd_event_default(&e) >= 0); assert_se(mkdtemp_malloc("/tmp/test-inotify-XXXXXX", &p) >= 0); + context.path = p; assert_se(sd_event_add_inotify(e, &a, p, IN_CREATE|IN_ONLYDIR, inotify_handler, &context) >= 0); assert_se(sd_event_add_inotify(e, &b, p, IN_CREATE|IN_DELETE|IN_DONT_FOLLOW, inotify_handler, &context) >= 0); @@ -500,6 +511,13 @@ static void test_inotify_one(unsigned n_create_events) { assert_se(sd_event_source_set_description(b, "1") >= 0); assert_se(sd_event_source_set_description(c, "2") >= 0); + assert_se(sd_event_source_get_inotify_path(a, &pp) >= 0); + assert_se(path_equal_or_inode_same(pp, p, 0)); + assert_se(sd_event_source_get_inotify_path(b, &pp) >= 0); + assert_se(path_equal_or_inode_same(pp, p, 0)); + assert_se(sd_event_source_get_inotify_path(b, &pp) >= 0); + assert_se(path_equal_or_inode_same(pp, p, 0)); + q = strjoina(p, "/sub"); assert_se(touch(q) >= 0); assert_se(sd_event_add_inotify(e, &d, q, IN_DELETE_SELF, delete_self_handler, &context) >= 0); @@ -556,7 +574,7 @@ TEST(pidfd) { int pidfd; pid_t pid, pid2; - assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0); + assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD) >= 0); pid = fork(); if (pid == 0) |