Survive a crash, and a reboot after one
kill, a closed window, a reboot: no SessionEnd arrives and the state file stays. Each case was tried rather than reasoned about, and one of the three was broken. A killed session was already handled -- the process is gone, so the file and its lock are removed within the 20 s liveness tick. An interrupted hook write left its temporary file behind forever; those are now swept once they are five minutes old, which is late enough that a hook part-way through writing one does not lose the update. The reboot case was the broken one. State files outlive a reboot and pids are handed out afresh, so "does /proc/<pid> exist" only answers "is some process wearing that number". Verified by giving an unrelated live process the pid of a dead session: the ghost sat in the panel as a session waiting for input, and would have stayed there forever, asking for an answer nobody could give. The pid is now pinned to the process start time from /proc/<pid>/stat, recorded when the state is written and compared when it is read. Files written before that field existed compare only on existence, as before, so a session open across the upgrade is not evicted. An abandoned flock needed nothing: the kernel drops it when the holder dies, so there is no deadlock to recover from.
This commit is contained in:
@@ -197,13 +197,33 @@ dump-layout`: рабочий каталог сессии сопоставляе
|
||||
Если zellij не используется, выключите в настройках: он стоит одного процесса
|
||||
раз в пару минут.
|
||||
|
||||
## Аварийное завершение
|
||||
|
||||
`kill`, закрытое окно, перезагрузка — `SessionEnd` не приходит, и файл остаётся.
|
||||
Разбор завалов проверен на каждом случае отдельно:
|
||||
|
||||
| Что осталось | Что с этим происходит |
|
||||
|---|---|
|
||||
| файл убитой сессии | процесса нет — файл и его `.lock` удаляются в пределах 20 с |
|
||||
| файл из прошлой загрузки | pid сверяется по времени старта процесса, а не только по наличию |
|
||||
| оборванная запись хука (`.tmp`) | удаляется, когда старше пяти минут |
|
||||
| незакрытый `flock` | ядро снимает блокировку при смерти процесса — тупика не бывает |
|
||||
|
||||
Сверка по времени старта — не перестраховка. Файлы состояния переживают
|
||||
перезагрузку, а pid после неё раздаются заново: проверка «есть ли `/proc/<pid>`»
|
||||
отвечает лишь «какой-то процесс с таким номером есть». Без этой сверки сессия,
|
||||
погибшая в аварии, висела бы в панели вечно, требуя ответа, которого некому дать.
|
||||
Проверено подстановкой постороннего живого процесса на тот же pid.
|
||||
|
||||
Порог в пять минут для `.tmp` тоже осмысленный: хук может писать такой файл
|
||||
прямо сейчас, и удаление свежего стоило бы потерянной записи.
|
||||
|
||||
Если хук вообще не смог опознать процесс claude, он пишет pid 0 — «неизвестно»,
|
||||
что никогда не путается с «мёртв»; такие записи истекают по возрасту, через
|
||||
36 часов.
|
||||
|
||||
## Известные шероховатости
|
||||
|
||||
- **Протухшие сессии.** Убитый терминал не присылает `SessionEnd`. Живость
|
||||
перепроверяется каждые 20 с по `/proc/<pid>`, файл удаляется — убитая сессия
|
||||
исчезает в пределах этого окна, а не висит вечно. Если хук вообще не смог
|
||||
опознать процесс claude, он записывает pid 0 — «неизвестно», что никогда не
|
||||
путается с «мёртв», — и такие записи истекают по возрасту, через 36 часов.
|
||||
- **`Stop` не отличает «закончил» от «сдался».** Оба читаются как «ждёт ввода»,
|
||||
и решение для вас в обоих случаях одно и то же.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user