# Жизненный цикл ядра и сервисов Все операции выполняются в потоке единственного `UASYNC` экземпляра, вне callbacks останавливаемых модулей. GUI передаёт команды в этот поток. ```c struct UTUN_INSTANCE* inst = utun_instance_create_from_str(ua, config); if (!inst || utun_core_start(inst) < 0) /* обработать ошибку */; if (chat_service_start(inst) < 0) /* обработать ошибку */; if (utun_service_start(inst) < 0) /* обработать ошибку */; chat_service_stop(inst); /* UTUN продолжает работать */ chat_service_start(inst); /* загружает сохранённые каналы */ utun_service_stop(inst); /* чат продолжает работать */ utun_instance_destroy(inst); ``` `utun_instance_init()` — сокращение для запуска ядра, UTUN и чата, если чат включён в конфигурации. Desktop GUI и Android запускают ядро и чат явно, без UTUN. Повторный start работающего сервиса и повторный stop допустимы. Ошибка старта сервиса откатывает созданные им ресурсы. `utun_instance_stop()` останавливает цикл приложения; освобождение ядра выполняет `utun_instance_destroy()`. | Владелец | Ресурсы | |---|---| | Ядро | Идентичность узла, реестр узлов и групп, SQLite, транспортные сокеты, NCD, маршрутизатор, общая репликация, время, мониторинг | | UTUN | Группа UTUN, запросы соединений из конфигурации, DATA binding, TUN, системные маршруты, NAT transport | | Чат | CHAT-группы, запросы подключения и join, экземпляры синхронизации каналов, chat API, медиа, личные сообщения, звонки и headless API | | Группа | Сессии пиров, её маршруты и логические каналы, планировщик подключения и recovery | | Сессия пира группы | NCD handle с момента CONNECTING, согласованные эпохи, состояние обмена таблицей, очередь отправки | SQLite открывается ядром один раз: `db_path/chats.db`, либо `:memory:`, если путь не задан. Остановка чата сохраняет каналы и сообщения в этой БД. В варианте `:memory:` данные сохраняются только до уничтожения ядра. Общий транспорт живёт, пока есть его владельцы. Закрытие запроса одной группы не разрывает соединение, нужное другой группе. При остановке группы отменяются её планировщики, запросы, таймеры и ожидания очередей; отправляется LEAVE, закрываются логические каналы маршрутизатора и удаляется её ожидающий транзит на общих соединениях. Транзит других групп сохраняется. Отложенный LEAVE может временно удерживать транспорт самостоятельно, не обращаясь к уже удалённой группе. Остановка чата сначала прекращает внешние команды и фоновые задания, затем закрывает медиа и сервисы, синхронизацию и группы, после чего освобождает chat core. `media_async_destroy()` дожидается завершения native workers и вызывает каждый ожидающий callback с `MEDIA_ASYNC_CANCELLED`, пока его контекст ещё существует. Результаты отменённых задач не записываются в БД. Это синхронное ожидание: длительное транскодирование или распознавание речи может задержать stop; принудительного прерывания этих библиотек нет. Статус транспорта UP подтверждает восстановление физического пути. READY сессии группы означает согласованный JOIN/ACCEPT и завершённый обмен её таблицей; именно его ждёт recovery. REINIT меняет эпохи обмена, сохраняя рабочие маршруты. Эпохи защищают от сообщений старой сессии и не задают срок жизни маршрута. Проверки: `test_services` проверяет независимый stop/start, общий NCD в CONNECTING, сохранение идентичности/сокетов/БД, повторную загрузку каналов, отмену workers, заблокированного медиа-потока, транзита и ожиданий заменённой очереди. `test_chat_join_e2e` проверяет join и распространение membership между узлами без UTUN-сервиса.