From 30fa2c3db21764139719c8cf4c8e8c35c8457014 Mon Sep 17 00:00:00 2001 From: Chris Down Date: Fri, 8 Nov 2024 22:10:52 -0800 Subject: [PATCH] clipctl: Use exponential backoff for clipmenud state change detection This was previously hardcoded to 100ms, which is way too high. Fixes #234. --- src/clipctl.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/clipctl.c b/src/clipctl.c index 64088c4..0b72b27 100644 --- a/src/clipctl.c +++ b/src/clipctl.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "config.h" @@ -68,7 +69,6 @@ static bool _nonnull_ should_enable(struct config *cfg, const char *mode_str) { /* The number of times to check if state was updated before giving up */ #define MAX_STATE_RETRIES 20 -#define USEC_IN_MS 1000 int main(int argc, char *argv[]) { _drop_(config_free) struct config cfg = setup("clipctl"); @@ -89,11 +89,30 @@ int main(int argc, char *argv[]) { expect(kill(pid, want_enable ? SIGUSR2 : SIGUSR1) == 0); dbg("Sent signal to pid %d\n", pid); + unsigned int delay_ms = 1; + unsigned int total_wait_ms = 0; + const unsigned int max_wait_ms = 1000; + for (size_t retries = 0; retries < MAX_STATE_RETRIES; ++retries) { if (is_enabled(&cfg) == want_enable) { return 0; } - usleep(100 * USEC_IN_MS); + + if (total_wait_ms >= max_wait_ms) { + break; + } + + struct timespec req = {.tv_sec = delay_ms / 1000, + .tv_nsec = (delay_ms % 1000) * 1000000L}; + struct timespec rem; + + while (nanosleep(&req, &rem) != 0) { + expect(errno == EINTR); + req = rem; + } + + total_wait_ms += delay_ms; + delay_ms *= 2; } die("Failed to %s clipmenud after %d retries\n",