From b5d276b38462ae24a35f4d0fce42eca758ea6c0c 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 | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/clipctl.c b/src/clipctl.c index 64088c4..7533633 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,13 +89,28 @@ int main(int argc, char *argv[]) { expect(kill(pid, want_enable ? SIGUSR2 : SIGUSR1) == 0); dbg("Sent signal to pid %d\n", pid); - for (size_t retries = 0; retries < MAX_STATE_RETRIES; ++retries) { + unsigned int delay_ms = 1; + unsigned int total_wait_ms = 0; + const unsigned int max_wait_ms = 1000; + + while (total_wait_ms < max_wait_ms) { if (is_enabled(&cfg) == want_enable) { return 0; } - usleep(100 * USEC_IN_MS); + + 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", - want_enable ? "enable" : "disable", MAX_STATE_RETRIES); + die("Failed to %s clipmenud within %d ms\n", + want_enable ? "enable" : "disable", max_wait_ms); }