0.131.1
Fixed
- Singleton flock снимался сразу — два инстанса на одном dataDir (A-002, ). High-дефект integrity из аудита 2026-06-24:
acquireFlockбралflock(LOCK_EX|LOCK_NB), но закрывал fd черезdefer f.Close()при возврате → flock (привязанный к open file description) снимался немедленно;releaseFlockбыл no-op. На WindowsacquireFlockвообще не вызывалLockFileEx. Итог: два параллельных инстанса на однойdataDir→ concurrent SQLite/PostgreSQL → порча БД + конфликт порта 14888. ТеперьacquireFlockвозвращает(*os.File, error)без закрытия fd;AcquireLockвозвращает*os.File, которыйtray.Runдержит весь lifecycle (defer ReleaseLock(dataDir, lockFile));ReleaseLock(dataDir, f)закрывает fd и удаляет файл. На unix —Flock(LOCK_EX|LOCK_NB)на держимом fd; на Windows —LockFileEx(LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY)(non-blocking, какLOCK_NB),ERROR_LOCK_VIOLATION→ дружелюбная ошибка. Дружелюбный PID-check fast-path оставлен, но безos.Removestale-файла (он перезаписывается атомарно черезTruncate(0)под локом — иначе TOCTOU-окно для конкурента). Тесты:singleton_test.go(unix: mutual-exclusion, reusability, PID-write, holds-file, empty-dataDir, dead-PID-recovered, live-PID-rejected) +singleton_windows_test.go(Windows-зеркало). - Критический момент: первый прогон
ocr reviewвыявил, что Windows-версия безLOCKFILE_FAIL_IMMEDIATELYбыла блокирующей — повесила бы старт tray при занятом локе; добавлен флаг + различениеERROR_LOCK_VIOLATIONот прочих ошибок.