Skip to content

[singleton] взять flock до connect_all — закрыть гонку подъёма / foreground / socket overwrite #88

Description

@enyonee

Симптом

Возможны два демона tunnelvault одновременно + два openvpn на один конфиг → бесконечный churn реконнектов (инцидент уже наблюдался в этой сессии).

Причина

Синглтон-гард _refuse_if_daemon_running (tunnelvault.py) проверяет живой демон через IPC-сокет. Но сокет поднимается только ПОСЛЕ connect_all, а настоящий атомарный flock (tv/daemon.py:write_pid_recover_stale_lock, kill-and-replace) берётся тоже после connect_all (в grandchild daemonize). Проверка и замок разнесены вокруг connect_all → окно дубля = вся длительность подъёма (openvpn init — десятки секунд).

Необойдённые дыры:

  1. Гонка/окно подъёма: второй запуск (или два одновременных sudo ./tvpn), стартовавший пока первый ещё поднимает тоннели, видит «сокета нет» → гард пропускает → оба идут в connect_all → два openvpn на один конфиг. flock/kill-and-replace арбитрируют уже ПОСЛЕ дубля.
  2. --foreground (launchd/systemd): исключён из гарда намеренно (политика kill-and-replace), но write_pid вызывается ПОСЛЕ connect_all → при рестарте поверх живого сначала дубль-connect, потом SIGTERM старому. Окно дубля = длительность connect_all.
  3. IPC-сокет перетирается без проверки живости: tv/ipc_server.py:126-133 (_cleanup_stale_socket) безусловно unlinkает существующий сокет → второй демон замещает сокет первого, первый осиротел и невидим для --status/--disconnect.

Направление фикса

Взять flock (или отдельный стартовый замок) ДО connect_all на ВСЕХ путях подъёма, включая --foreground — тогда refuse/kill-and-replace решается до поднятия хоть одного тоннеля. В _cleanup_stale_socket перед unlink пробовать connect: успех = «жив, другой демон» → не биндить.

Требует аккуратной работы с lifecycle демона (flock через double-fork) + живой проверки.

Контекст: частичный фикс уже влит (44776bc синглтон-гард закрыл узкий интерактивный кейс; e28f0d1 починил регресс --reconnect). Это issue — про оставшуюся гонку/полноту.

Найдено адверсариальным ревью (singleton ось), 2026-07-02.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingp1-high

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions