diff options
author | Lennart Poettering <lennart@poettering.net> | 2013-12-13 04:03:30 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2013-12-13 04:06:43 +0100 |
commit | 12179984a38fe74581333fbcdc11c822d81f505f (patch) | |
tree | 0fbd335d4c9f2d96df48a5e7a7f7f816c7eca347 /src/libsystemd-bus/test-event.c | |
parent | 7b77ed8cf36e8eca6017791626044b61ae2d68e7 (diff) |
event: when unreffing an event source from its own handler, detach fd from epoll
The pattern of unreffing an IO event source and then closing its fd is
frequently seen in even source callbacks. Previously this likely
resultet in us removing the fd from the epoll after it was closed which
is problematic, since while we were dispatching we always kept an extra
reference to event source objects because we might still need it later.
Diffstat (limited to 'src/libsystemd-bus/test-event.c')
-rw-r--r-- | src/libsystemd-bus/test-event.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/src/libsystemd-bus/test-event.c b/src/libsystemd-bus/test-event.c index 5317008a87..28ef6a3692 100644 --- a/src/libsystemd-bus/test-event.c +++ b/src/libsystemd-bus/test-event.c @@ -28,9 +28,15 @@ static int prepare_handler(sd_event_source *s, void *userdata) { return 1; } -static bool got_a, got_b, got_c; +static bool got_a, got_b, got_c, got_unref; static unsigned got_d; +static int unref_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + sd_event_source_unref(s); + got_unref = true; + return 0; +} + static int io_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { log_info("got IO on %c", PTR_TO_INT(userdata)); @@ -155,18 +161,26 @@ static int exit_handler(sd_event_source *s, void *userdata) { int main(int argc, char *argv[]) { sd_event *e = NULL; - sd_event_source *w = NULL, *x = NULL, *y = NULL, *z = NULL, *q = NULL; + sd_event_source *w = NULL, *x = NULL, *y = NULL, *z = NULL, *q = NULL, *t = NULL; static const char ch = 'x'; - int a[2] = { -1, -1 }, b[2] = { -1, -1}, d[2] = { -1, -1}; + int a[2] = { -1, -1 }, b[2] = { -1, -1}, d[2] = { -1, -1}, k[2] = { -1, -1 }; assert_se(pipe(a) >= 0); assert_se(pipe(b) >= 0); assert_se(pipe(d) >= 0); + assert_se(pipe(k) >= 0); assert_se(sd_event_default(&e) >= 0); assert_se(sd_event_set_watchdog(e, true) >= 0); + /* Test whether we cleanly can destroy an io event source from its own handler */ + got_unref = false; + assert_se(sd_event_add_io(e, k[0], EPOLLIN, unref_handler, NULL, &t) >= 0); + assert_se(write(k[1], &ch, 1) == 1); + assert_se(sd_event_run(e, (uint64_t) -1) >= 1); + assert_se(got_unref); + got_a = false, got_b = false, got_c = false, got_d = 0; /* Add a oneshot handler, trigger it, re-enable it, and trigger @@ -227,6 +241,8 @@ int main(int argc, char *argv[]) { close_pipe(a); close_pipe(b); + close_pipe(d); + close_pipe(k); return 0; } |