From 31658a34ffaebab74a90db0ce876c86f2ccf3e99 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 20 May 2026 09:42:00 +1000 Subject: [PATCH] tools/record: fix broken autorestart for timeouts >=5s The autorestart feature used the epoll timeout for detecting when no events happend. This conflicts with our wall clock timerfd (to print the current time every 5s) which is hooked into the same epoll. Any autorestart timeout >=5s would get that timerfd fired which is interpreted as events and thus prevents the autorestart from closing the file. Fix this by removing the timerfd and instead print the wall clock time whenever we get events and it's past a delta. This means we can also drop the hacks to remember if we did have events since the last timer to avoid spamming empty logs with "Current time: ..." lines. Closes #1291 Part-of: --- tools/libinput-record.c | 64 ++++++++++------------------------------- 1 file changed, 15 insertions(+), 49 deletions(-) diff --git a/tools/libinput-record.c b/tools/libinput-record.c index 451de97d..a957f45e 100644 --- a/tools/libinput-record.c +++ b/tools/libinput-record.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -130,8 +129,7 @@ struct record_context { struct list sources; struct { - bool had_events_since_last_time; - bool skipped_timer_print; + usec_t last_wall_time; } timestamps; bool had_events; @@ -2075,21 +2073,6 @@ print_wall_time(struct record_context *ctx) } } -static void -arm_timer(int timerfd) -{ - time_t t = time(NULL); - struct tm tm; - struct itimerspec interval = { - .it_value = { 0, 0 }, - .it_interval = { 5, 0 }, - }; - - localtime_r(&t, &tm); - interval.it_value.tv_sec = 5 - (tm.tm_sec % 5); - timerfd_settime(timerfd, 0, &interval, NULL); -} - static struct source * add_source(struct record_context *ctx, int fd, @@ -2135,35 +2118,12 @@ signalfd_dispatch(struct record_context *ctx, int fd, void *data) ctx->stop = true; } -static void -timefd_dispatch(struct record_context *ctx, int fd, void *data) -{ - char discard[64]; - - (void)read(fd, discard, sizeof(discard)); - - if (ctx->timestamps.had_events_since_last_time) { - print_wall_time(ctx); - ctx->timestamps.had_events_since_last_time = false; - ctx->timestamps.skipped_timer_print = false; - } else { - ctx->timestamps.skipped_timer_print = true; - } -} - static void evdev_dispatch(struct record_context *ctx, int fd, void *data) { struct record_device *this_device = data; - if (ctx->timestamps.skipped_timer_print) { - print_wall_time(ctx); - ctx->timestamps.skipped_timer_print = false; - } - ctx->had_events = true; - ctx->timestamps.had_events_since_last_time = true; - now_in_us(&ctx->timestamps.last_event_time); handle_events(ctx, this_device); } @@ -2176,7 +2136,6 @@ libinput_ctx_dispatch(struct record_context *ctx, int fd, void *data) * are already processed in handle_events */ libinput_dispatch(ctx->libinput); handle_libinput_events(ctx, ctx->first_device, true); - now_in_us(&ctx->timestamps.last_event_time); } static void @@ -2185,9 +2144,7 @@ hidraw_dispatch(struct record_context *ctx, int fd, void *data) struct hidraw *hidraw = data; ctx->had_events = true; - ctx->timestamps.had_events_since_last_time = true; handle_hidraw(hidraw); - now_in_us(&ctx->timestamps.last_event_time); } static int @@ -2205,10 +2162,20 @@ dispatch_sources(struct record_context *ctx) if (count < 0) return -errno; + if (count > 0) { + usec_t now = usec_from_now(); + usec_t dt = usec_delta(now, ctx->timestamps.last_wall_time); + if (usec_cmp(dt, usec_from_seconds(5)) > 0) { + ctx->timestamps.last_wall_time = now; + print_wall_time(ctx); + } + } + for (i = 0; i < count; ++i) { source = ep[i].data.ptr; if (source->fd == -1) continue; + source->dispatch(ctx, source->fd, source->user_data); } @@ -2222,7 +2189,7 @@ mainloop(struct record_context *ctx) struct source *source; struct record_device *d = NULL; sigset_t mask; - int sigfd, timerfd; + int sigfd; assert(!list_empty(&ctx->devices)); @@ -2237,10 +2204,6 @@ mainloop(struct record_context *ctx) sigfd = signalfd(-1, &mask, SFD_NONBLOCK); add_source(ctx, sigfd, signalfd_dispatch, NULL); - timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); - add_source(ctx, timerfd, timefd_dispatch, NULL); - arm_timer(timerfd); - list_for_each(d, &ctx->devices, link) { struct hidraw *hidraw; @@ -2300,6 +2263,8 @@ mainloop(struct record_context *ctx) print_device_description(d); iprintf(d->fp, I_DEVICE, "events:\n"); } + + ctx->timestamps.last_wall_time = usec_from_now(); print_wall_time(ctx); if (ctx->libinput) { @@ -2662,6 +2627,7 @@ main(int argc, char **argv) struct record_context ctx = { .timeout = usec_from_uint64_t(0), .show_keycodes = false, + .timestamps.last_wall_time = usec_from_uint64_t(0), }; struct option opts[] = { { "autorestart", required_argument, 0, OPT_AUTORESTART },