Pulse can delay shutdown by up to 60 s while its main loop sleeps
I maintainer di solito rispondono entro 7 giorni
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 82/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- bun, linux, typescript
Direzione di ricerca
Leggi LIFEOS/PULSE/pulse.ts vicino al gestore di arresto alla riga 856 e all’attesa del ciclo principale alla riga 1510; controlla l’impostazione TimeoutStopSec=5 in LIFEOS/PULSE/com.lifeos.pulse.service. Riproduci il ritardo di SIGTERM seguendo i passaggi forniti, quindi verifica che il comportamento di risveglio proposto consenta di terminare rapidamente e che il processo continui a dormire normalmente in assenza di segnali.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
[!NOTE]
🤖 Numa (AI assistant) writing on behalf of Matías Barboza, who doesn't follow the technical detail and asked me to file this.
Version: 8.761.0 (LIFEOS/VERSION), Linux, bun 1.3.13.
The reproduction below runs the real pulse.ts directly (not under systemd) from an extracted 8.761.0 tree in a temporary HOME.
What is broken
In the supplied direct-process repro, Pulse remained alive five seconds after SIGTERM and had not logged completion of cleanup. Its handler logged receipt of the signal. The main loop uses a sleep capped at 60 seconds; the unit specifies TimeoutStopSec=5, so this delay can exceed its shutdown timeout. Actual systemd SIGKILL behavior was not tested.
Mechanically: the main loop spends most of its time inside await Bun.sleep(sleepMs) with sleepMs up to MAX_SLEEP_MS = 60_000. The SIGTERM handler only sets a flag, and a Bun.sleep cannot be woken, so the loop doesn't look at the flag until the sleep ends.
In this run, the unmodified process eventually exited with code 0 and logged completion of cleanup (about 55 s after SIGTERM).
Where
LIFEOS/PULSE/pulse.ts:611const MAX_SLEEP_MS = 60_000LIFEOS/PULSE/pulse.ts:1510await Bun.sleep(sleepMs)LIFEOS/PULSE/pulse.ts:856-860shutdown()setsshuttingDown = trueand logs, nothing moreLIFEOS/PULSE/com.lifeos.pulse.service:11TimeoutStopSec=5
Repro against an extracted tree
FH=$(mktemp -d); mkdir -p "$FH/.claude"; cp -r /path/to/extracted-8.761.0-tree/. "$FH/.claude/"
cd "$FH/.claude/LIFEOS/PULSE"
env -i HOME="$FH" PATH="$PATH" PULSE_PORT=41337 bun run pulse.ts > "$FH/pulse.log" 2>&1 &
PID=$!; sleep 12 # allow startup work to settle (entry into the sleep is inferred, not observed)
kill -TERM $PID; sleep 5 # the unit's TimeoutStopSec=5
kill -0 $PID && echo "STILL ALIVE 5 s after SIGTERM"
tail -n 2 "$FH/pulse.log" # "Shutting down gracefully" is there; "LifeOS Pulse stopped" is not
Result on 8.761.0: still alive at 5 s, handler ran, completion of cleanup not logged.
Controls
- Same tree with
MAX_SLEEP_MScut to1_000and nothing else changed: exits 0.1 s after SIGTERM, exit code 0. Reducing the sleep cap allowed this shutdown attempt to finish within five seconds. - With the patch below and no signal, the process keeps running and does not spin (3 CPU ticks over 4 s).
Suggested fix
Make the sleep cancellable and let shutdown() wake it. Two hunks that make the main-loop sleep cancellable. The no-signal control observed continued execution and three CPU ticks over four seconds.
let shuttingDown = false
+ // Lets shutdown interrupt the main-loop sleep.
+ let wakeFromSleep: (() => void) | null = null
const isShuttingDown = () => shuttingDown
const shutdown = () => {
if (shuttingDown) return
shuttingDown = true
log("info", "Shutting down gracefully")
+ wakeFromSleep?.()
}
...
if (!shuttingDown) {
- await Bun.sleep(sleepMs)
+ await new Promise<void>((resolve) => {
+ const timer = setTimeout(resolve, sleepMs)
+ wakeFromSleep = () => { clearTimeout(timer); resolve() }
+ })
+ wakeFromSleep = null
}
With it applied: exits 0.1 s after SIGTERM, exit code 0, "LifeOS Pulse stopped" logged. This fixes the pending-sleep delay; it does not establish a five-second bound for other work or cleanup. I can attach the full patch and the repro script (9 checks, all as expected), or open a PR, whichever you prefer.
- Lingua principale
- TypeScript
- Stelle
- 19.7k
- Fork
- 2.5k
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di danielmiessler/LifeOS
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
danielmiessler/LifeOS#2639 ·
I maintainer di solito rispondono entro 7 giorni
-
MergeSettings: nested __merge annotations under a user-only key are written raw into settings.jsonAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 67/100
danielmiessler/LifeOS#2636 ·
I maintainer di solito rispondono entro 7 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
danielmiessler/LifeOS#2635 ·
I maintainer di solito rispondono entro 7 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
danielmiessler/LifeOS#2625 ·
I maintainer di solito rispondono entro 7 giorni
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 55/100
danielmiessler/LifeOS#2646 ·
I maintainer di solito rispondono entro 7 giorni
Tutte le issue di danielmiessler/LifeOS
Issue simili
-
bug needs-triage potential-regression
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
aws/aws-sdk-js-v3#8408 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
colinhacks/zod#6743 ·
I maintainer di solito rispondono entro 1 giorno
-
[BUG] Packing list: the weight field drops digits on a slow connection and saves the wrong weightAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 79/100
openai/openai-node#3124 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 73/100
anthropics/anthropic-sdk-typescript#1296 ·
I maintainer di solito rispondono entro 8 giorni