From 182aa340088bb05875fa67666652883fc14ecf22 Mon Sep 17 00:00:00 2001 From: Erki Aas Date: Wed, 15 Apr 2026 16:22:27 +0300 Subject: [PATCH] add retry logic to openrgb commands for boot-time stability OpenRGB can crash (SIGABRT) during early boot when device enumeration hasn't completed yet. Retry failed commands up to 4 times with a 3-second delay to let initialization finish. Co-Authored-By: Claude Opus 4.6 (1M context) --- controller/openrgb/client.go | 39 +++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/controller/openrgb/client.go b/controller/openrgb/client.go index 12e042e..a256176 100644 --- a/controller/openrgb/client.go +++ b/controller/openrgb/client.go @@ -2,7 +2,14 @@ package openrgb import ( "fmt" + "log" "os/exec" + "time" +) + +const ( + maxRetries = 4 + retryDelay = 3 * time.Second ) // Client controls RGB devices via the openrgb CLI. @@ -29,21 +36,33 @@ func (c *Client) Close() error { return nil } +// run executes an openrgb command with retries to handle transient failures +// during early boot when device enumeration may not be complete. +func (c *Client) run(args ...string) error { + var lastErr error + for attempt := range maxRetries { + cmd := exec.Command(c.bin, args...) + out, err := cmd.CombinedOutput() + if err == nil { + return nil + } + lastErr = fmt.Errorf("openrgb %v: %w\n%s", args, err, out) + if attempt < maxRetries-1 { + log.Printf("openrgb command failed (attempt %d/%d), retrying in %v: %v", + attempt+1, maxRetries, retryDelay, lastErr) + time.Sleep(retryDelay) + } + } + return lastErr +} + // SetAllOff sets all devices to black (off) using direct mode. func (c *Client) SetAllOff() error { - cmd := exec.Command(c.bin, "--mode", "direct", "--color", "000000") - if out, err := cmd.CombinedOutput(); err != nil { - return fmt.Errorf("openrgb set off: %w\n%s", err, out) - } - return nil + return c.run("--mode", "direct", "--color", "000000") } // SetAllOn sets all devices to the given color. func (c *Client) SetAllOn(r, g, b byte) error { color := fmt.Sprintf("%02X%02X%02X", r, g, b) - cmd := exec.Command(c.bin, "--mode", "direct", "--color", color) - if out, err := cmd.CombinedOutput(); err != nil { - return fmt.Errorf("openrgb set on: %w\n%s", err, out) - } - return nil + return c.run("--mode", "direct", "--color", color) }