aboutsummaryrefslogtreecommitdiffstats
path: root/breaktimer.sh
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-06-29 11:07:41 +0200
committerDanilo M. <danix@danix.xyz>2026-06-29 11:07:41 +0200
commit12528dccd3a1c7043fb14343c0830345f5015fbf (patch)
treeadeacec67742f333fc79dfed1fd5c021efe898a7 /breaktimer.sh
parentabe41b57d39e6fd2d88a1e5e20c921b96d54b65b (diff)
downloadbreaktimer-12528dccd3a1c7043fb14343c0830345f5015fbf.tar.gz
breaktimer-12528dccd3a1c7043fb14343c0830345f5015fbf.zip
Fix duplicate daemon spawn on login via atomic PID claim
Replace the check-then-write singleton guard in run_loop with an atomic noclobber PID-file claim. The old guard read the PID file then wrote it in two steps; two starts racing (e.g. a fast double-login) could both read a stale PID and spawn duplicate daemons. With noclobber only the first writer creates the file; the loser aborts, and a stale PID from a previous session is taken over rather than duplicated. Also document install (~/bin copy) and autostart in CLAUDE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'breaktimer.sh')
-rwxr-xr-xbreaktimer.sh19
1 files changed, 12 insertions, 7 deletions
diff --git a/breaktimer.sh b/breaktimer.sh
index 4ce5a42..9a9c5fa 100755
--- a/breaktimer.sh
+++ b/breaktimer.sh
@@ -107,15 +107,20 @@ notify_back() {
# ---------- Loop principale ----------
run_loop() {
- # singleton: rifiuta se un altro daemon vivo possiede gia' il PID file.
- # Evita due loop che si calpestano gli stessi file di stato.
+ # singleton: rivendica il PID file in modo atomico con noclobber.
+ # check-then-write avrebbe una finestra di race: due loop avviati insieme
+ # (es. doppio login) leggono entrambi un PID file stantio e partono. Con
+ # noclobber solo il primo crea il file; il secondo fallisce e poi decide.
local owner
- owner="$(cat "$PID_FILE" 2>/dev/null)"
- if [ -n "$owner" ] && [ "$owner" != "$$" ] && kill -0 "$owner" 2>/dev/null; then
- echo "breaktimer: gia' in esecuzione (PID $owner), run annullato" >&2
- exit 1
+ if ! ( set -o noclobber; echo "$$" > "$PID_FILE" ) 2>/dev/null; then
+ owner="$(cat "$PID_FILE" 2>/dev/null)"
+ if [ -n "$owner" ] && [ "$owner" != "$$" ] && kill -0 "$owner" 2>/dev/null; then
+ echo "breaktimer: gia' in esecuzione (PID $owner), run annullato" >&2
+ exit 1
+ fi
+ # PID file stantio (owner morto): rivendicalo.
+ echo "$$" > "$PID_FILE"
fi
- echo "$$" > "$PID_FILE"
echo "running" > "$STATE_FILE"
echo "working" > "$PHASE_FILE"
local count=0