Record instance lifecycle fixes, contracts and sanitizer audit evidence
This commit is contained in:
1 parent
4219d5ce1d
commit
8640b45e99
1 file changed
+99
@@ -0,0 +1,99 @@
|
||||
Аудит utun_instance — 26.10.2026
|
||||
|
||||
Объём
|
||||
Полностью прочитаны utun_instance.c/.h и прежний utun_instance_doc.md; сверены
|
||||
вызовы конструкторов/start/stop/reload из CLI/встраивания и связанные механизмы
|
||||
ETCP/NCD/STCP, sockets, logger, очередей, SQLite и независимых сервисов.
|
||||
Заголовок и документ переписаны по фактическому коду. Core-разделы
|
||||
doc/service_lifecycle.md согласованы; весь поперечный документ остаётся [~].
|
||||
Это не полный аудит реализаций chat/call/radio/stream или GUI/Android.
|
||||
|
||||
Исправления
|
||||
- Activity/peer-sleep подписки удерживают снятые записи до выхода из внешней
|
||||
рассылки. Безопасны удаление себя/соседа, вложенное событие и добавление новой
|
||||
подписки. Повтор fn+arg не дублируется; более новая эффективная activity
|
||||
отменяет остаток старой рассылки. OOM обеих подписок логируется.
|
||||
- Конструкторы проверяют UASYNC/config/path до побочных действий; общий путь
|
||||
создания освобождает частичные ресурсы, сохраняя caller config при отказе.
|
||||
Проверяются crypto derivation, запись/close временного файла, создание каталогов
|
||||
и индекс сетей. Старый TCP-реестр индексируется по node_id, а не указателю link.
|
||||
- Выбранный путь общего logger копируется в постоянный буфер; освобождение config
|
||||
больше не оставляет заимствованную строку в logger. Уже открытый файловый logger
|
||||
сохраняет первый путь при создании/reload другого instance.
|
||||
- Reload готовит config/firewall/networks до изменения ресурсов. Смена владельцев
|
||||
(в том числе db_path, control, TUN/NAT/proxy), подсетей или automatic server-конфига
|
||||
пересоздаёт ядро с прежними core/UTUN/chat/running. Повторные имена server также
|
||||
выбирают полный путь, сохраняя отдельные секции parser без неоднозначного matching.
|
||||
- Manual reload сравнивает все server-параметры и IPv6 scope по конфигурации,
|
||||
сохраняя неизменённые sockets/ephemeral ports. TCP listener закрывается вместе
|
||||
с правильной TCP-моделью; UDP создаётся/удаляется своим API. Устранён лог через
|
||||
освобождённое имя. Probe и endpoints других владельцев не удаляются по отсутствию
|
||||
server-секции. Конфигурационные clients обновляются также без UTUN; неизменённые
|
||||
handles/таймеры сохраняются, копии не ссылаются на освобождённый config.
|
||||
- Destroy обходит sockets/connections от свежей головы после callbacks,
|
||||
освобождает старые TCP queue entries и оставшиеся transport-подписки.
|
||||
Повторный destroy/start/reload при разрушении отклоняется; SQLite close ошибки
|
||||
видны, BUSY завершается close_v2 до финализации заимствованных SQL-объектов.
|
||||
- Три headless bind разбираются одинаково: IPv4 literal, полный decimal port
|
||||
0..65535. Port=0 выбирает ОС; плохое значение не открывает порт по умолчанию.
|
||||
Отказ listener не фатален для чата, частичный контекст очищается.
|
||||
- Call/radio headless stop освобождает контекст/кодеки, снимает клиентов с UASYNC
|
||||
и отменяет cleanup/mix таймеры. Их отказы при старте дают rollback.
|
||||
- UBSan нашёл невыровненный PCM после 11-байтового headless заголовка и uint64_t
|
||||
hop-list в radio_recv. Оба читаются через выровненное хранилище; тест рации также
|
||||
использует memcpy вместо int16_t* к невыровненному payload. Wire не менялся.
|
||||
- Из заголовка удалено объявление несуществующего utun_instance_run; poll принадлежит
|
||||
caller. Уточнены владение, состояния, ошибки init/reload, подписки и диагностика.
|
||||
|
||||
Контракты и ограничения
|
||||
Все lifecycle операции выполняются в потоке своего UASYNC, stop/destroy/reload —
|
||||
вне callbacks останавливаемых модулей. UASYNC принадлежит caller и живёт до конца
|
||||
очистки. Core start при отказе сохраняет подготовленные ресурсы для retry/destroy;
|
||||
init при отказе позднего сервиса сохраняет ранее запущенные сервисы.
|
||||
Create уже выполняет I/O и создаёт listeners/SQLite/router/proxy/monitoring.
|
||||
Create_from_str требует временного файла /tmp и не является чистым buffer parser.
|
||||
Logger общий для процесса; его изменения и config updater не входят в транзакцию reload.
|
||||
|
||||
Partial reload не атомарен: отказ endpoint сохраняет новый config и отсутствие
|
||||
endpoint для следующей попытки. Подготовка clients при ошибке сохраняет прежние
|
||||
самостоятельные handles. Full reload возвращает NULL, если новое ядро не удалось
|
||||
создать/запустить после уничтожения старого; caller использует возвращённый указатель.
|
||||
Порядок списков/padding модели может консервативно выбрать restart. IPv6 selector
|
||||
temporary/permanent меняет адрес в модели при разрешении, поэтому повторный reload
|
||||
может консервативно пересоздать такой endpoint.
|
||||
Caller завершает borrowed statements/backups; close_v2 не разрешает использовать
|
||||
уничтоженный instance. Живые ресурсы в diagnose_leaks сами по себе не доказывают утечку.
|
||||
Отменённые heap-таймеры UASYNC освобождаются при следующем poll, а pool cache — при
|
||||
уничтожении UASYNC; тест сверяет active/counters и общий баланс после обоих шагов.
|
||||
|
||||
Проверки
|
||||
- Полная обычная сборка PASS: /tmp/utun-instance-audit-build-final.log.
|
||||
- Первый полный check.sh: 196/196 PASS, 0 failed/0 skipped; proxy9/9, burst1/1,
|
||||
load8/8, 134217728 байт, 189с; /tmp/utun-instance-audit-final-check.log.
|
||||
Он предшествовал последней правке выравнивания radio hop-list.
|
||||
- Профиль после исправлений: test_instance_contract, test_services, test_ncd_config,
|
||||
test_tun_route, test_etcp_transport, test_stcp, test_node_conn_direct,
|
||||
test_call_headless, test_radio_headless PASS; три изменённых адресных теста
|
||||
повторены в /tmp/utun-instance-audit-final-test_*.log.
|
||||
- Новый test_instance_contract проверяет nested callbacks/OOM, constructor ownership,
|
||||
правильный TCP queue index, неизменённые ephemeral endpoints, malformed config,
|
||||
отказ network queue/create endpoint с retry, UDP/TCP замену и удаление listener,
|
||||
duplicate server names, full reload с сохранением stopped/core-only состояния,
|
||||
SQLite BUSY/finalize, другой UASYNC, db_path restart, recursive mkdir и жизнь
|
||||
logger path после освобождения config. Headless: три port=0, реальные TCP-клиенты,
|
||||
stop/start с сохранением SQLite, три timer faults и malformed binds.
|
||||
- ASAN/UBSan/LSan 11/11 PASS, detect_leaks=1, halt_on_error=1:
|
||||
те же девять instance/transport/headless тестов плюс config_parser/config_updater.
|
||||
Итог: /tmp/utun-instance-audit-asan-results-complete.log; отдельные логи
|
||||
/tmp/utun-instance-audit-asan-complete-test_*.log.
|
||||
Отдельная копия /tmp/utun-config-instance-asan-20261026, все lib/src/Opus
|
||||
инструментированы согласованно. Встроенный Opus не перекрывает CFLAGS в этой
|
||||
тестовой копии; рабочая normal-сборка с sanitizer-объектами не смешивалась.
|
||||
Сборки: /tmp/utun-instance-audit-asan-build.log,
|
||||
/tmp/utun-instance-audit-asan-core-final.log и ...-asan-tests-build.log.
|
||||
Ранние наборы 9/11 и 10/11 выявили описанные alignment defects; окончательный
|
||||
набор после исправления обеих причин полностью PASS.
|
||||
- git diff --check PASS. Нативные Windows/FreeBSD сборки/runtime, GUI/Android и
|
||||
аппаратные TUN/media в этом этапе не запускались; Linux TUN lifecycle проверен mock-тестом.
|
||||
|
||||
Окончательный штатный check.sh после последней правки: результат дописывается ниже.
|
||||
Reference in new issue
Block a user