Отладка: логи, список fail-fast и учения
В XServer нет админ-панели; отладка держится на трёх вещах: структурных логах старта, ошибках fail-fast, называющих точное поле, и тестовых / ученийных базлайнах, которые вы можете запустить сами. Глава превращает их в ваш первый справочник отладчика.
Обзор
6.1 Введение
Сервер без интерфейса управления обязан вырастить отладочные возможности в другом месте. Выбор XServer: сделать диагностику детерминированными событиями — одна и та же конфигурация и состояние всегда дают одни и те же строки лога в том же порядке; ошибки конфигурации всегда называют конкретное поле при старте и завершают процесс, никогда не «работая с дефектом». Детерминизм = сопоставимость: у каждой аномальной строки, которую вы видите, есть близнец в тест-кейсах исходников.
Три секции покрывают три домена отказов: период старта (порядок лога + список fail-fast), период остановки (последовательность корректной остановки) и период работы (тестовые и ученийные базлайны).
6.2 Система логирования
Словарь последовательности старта
Глава 2 разбирала нормальную последовательность построчно; здесь добавляем аномальные ветви — что значит, если строка «не появилась» или «выглядит иначе»:
| Наблюдение | Диагноз | Действие |
|---|---|---|
Остановилось на config load failed | Недопустимое поле xs.json (см. 6.3) | Исправить поле, названное в ошибке |
Нет engine started | Не поднялся движок конкурентности (редко) | Проверить ресурсы системы / лимиты потоков |
Нет script loaded | Провал компиляции TCC — ошибка содержит вывод компилятора | Чинить C-код; ошибки указывают строки devfile |
Строки с [префиксом приложения] нет | ServiceInit не выполнился или не логирует | Проверить devfile и экспорт Init |
Остановилось на bind failed | Порт занят / не хватает прав | netstat по порту; при нескольких слушателях занятые откатываются |
gen N растёт снова и снова | Идут горячие перезагрузки (или рестарты) | Выяснить, кто подаёт reload |
Последовательность остановки
Пять фаз после Ctrl+C / SIGTERM (тестовый базлайн содержит утверждения на последние две строки):
[xs] stopping (прекратить приём и утилизировать скрипты → дождаться терминальных состояний сети → утилизировать custom → вычистить очередь деструкций) [xs] engine stopped [xs] bye
Откуда берутся логи приложения
Строки с префиксом вроде [demo] — это ваш собственный printf: логирование скриптов XServer — стандартный вывод. Хотите структуру — берите семейство logger из xrt (76 API: уровни, форматирование, несколько приёмников), см. блок «Что дальше».
6.3 Список ошибок fail-fast
У валидации xs.json 21 тест-кейс (A-матрица func_test), все с утверждением «exit=1 и ошибка называет конкретное поле». Частые выдержки:
| Сообщение (выдержка) | Причина | Исправление |
|---|---|---|
field 'services' expect array | Корневой services не массив | Проверить структуру JSON и правописание |
| duplicate name ... | Повтор имени server / host | имена server глобально уникальны; host — уникальны внутри server |
| missing port | У сервиса не-custom нет port | Добавить port (1–65535) |
| tls on udp | Сервису udp назначен tls | Убрать — в UDP нет понятия TLS |
| recv limit out of range | Например udp recv_limit > 65535 | Уменьшить до диапазона |
| static headers зарезервированный заголовок | В static.headers попал зарезервированный заголовок вроде Transfer-Encoding | Убрать один из 8 зарезервированных |
| ключ error_pages вне диапазона | Код состояния вне 400–599 | Исправить ключ |
| корень статики отсутствует | Каталог в host path не существует | Создать каталог или сменить path |
certificate uses RSA but private key uses EC | Несовпадение семейств алгоритмов сертификата и ключа | Взять парные cert/key (диагностика называет оба) |
| expects exactly one supported PEM block | В файле ключа несколько / битых блоков PEM | Оставить ровно один полный поддерживаемый блок |
Проектная позиция: лучше отказать в старте, чем молча деградировать — вы никогда не встретите самый опасный тихий отказ «настроили TLS, а фактически работает открытый текст».
6.4 Остановка и учения
«Не только ли у меня сломано?» — встроенные в репозиторий базлайны и есть контрольная группа для ответа:
| Базлайн | Содержимое | Применение |
|---|---|---|
test.bat / test.sh | Сборка → дымовой тест (эхо HTTP/WS/TCP/UDP + 11 утверждений по логу) → функциональная матрица → матрица перезагрузок, одной командой | Первым делом при подозрении на среду |
func_test | 40 сценариев с утверждениями: 21 случай fail-fast конфигурации, векторы обхода путей, штормы reload | Точная локализация поведения на границах протоколов |
reload_matrix | Проверка передачи поколений на 7 эндпоинтах, четыре протокола × TLS | Сверка поведения горячей перезагрузки |
drill | Шестичасовые учения: slowloris, бомбы пайплайнов, бомбы перезагрузок битых скриптов + замеры RSS | Подозрения на память / стабильность |
routebench | Сравнение задержек на одной машине с Go / PHP / FastAPI | Оценка регрессий производительности |
Отладка на уровне памяти (падения, выход за границы, утечки) использует систему отладки памяти xrt: канарейки спереди и сзади, очереди изоляции UAF, кольцевой журнал событий аллокации, отчёты TEXT/JSON — включается в конфигурации сборки хоста; см. главу 6 учебника xrt по ссылке в конце.
6.5 Контракт
- Детерминизм: одинаковый вход всегда даёт одинаковую последовательность лога — любая «мистика» указывает на конфигурацию или среду.
- Fail-fast: ошибки старта все называют поле и завершают процесс; устойчивые ошибки времени работы проявляются кодами состояния на уровне соединения / разрывами и не роняют процесс.
- Порядок отладки: сначала лог (найти фазу) → затем список fail-fast (сопоставить сообщение) → в конце базлайны (изолировать факторы среды).
Частые ошибки
- Симптом
- Изменили port / workers / добавили host — поведение не меняется.
- Причина
- Большинство полей xs.json собирается при старте; в рантайме горячо обновляются только скрипты и сертификаты (через reload). Структурные изменения конфигурации требуют рестарта.
/* правим xs.json и просто ждём */
vim xs.json # порт не сменился?/* скрипты/сертификаты: подать reload (том 4)
* структурные изменения: рестарт процесса */- Симптом
- Скрипт подключает старый заголовок, которого нет по правильному пути; компиляция ведёт себя странно (используются неверные объявления).
- Причина
- Относительный поиск по dev_inc при откате цепляет одноимённый файл из текущего рабочего каталога — в тестовом наборе есть специальный кейс с «заголовком-приманкой», охраняющий эту границу.
#include <config.h>
/* куда попало: includes/config.h
* или другой config.h из CWD? *//* уникальные имена вместо общих */
#include <myapp_config.h>- Симптом
- После Ctrl+C процесс долго не исчезает.
- Причина
- Корректная остановка ждёт естественного завершения живых соединений (без принудительного демонтажа). Длинные соединения (WebSocket / push) растягивают ожидание.
/* «дедлок!» → сразу kill -9
* теряем и место отладки, и семантику корректности *//* посмотреть, на какой фазе лог;
* дать приложению /shutdown для завершения соединений;
* внешний тайм-аут — от сервис-менеджера (глава 37) */Упражнения
Намеренно создайте три ошибки конфигурации из списка 6.3 (например dup name, tls on udp, error_pages вне диапазона), зафиксируйте сообщения и исправьте.
Перемешайте нормальный лог старта и отдайте напарнику восстановить порядок по фазам сборки; затем удалите одну строку — пусть скажет, «какого шага не хватает и где застрянет следующий».
Напишите модуль логирования на уровне modules: на каждый запрос выводить метод, путь, код состояния, длительность (подсказка: высокоточные часы xrt; в рамках контрактных линий главы 3 определите, что ему доступно). По канареечной логике drill проверьте, что функциональность не задета.
Итоги
| Тезис | Вывод |
|---|---|
| Три оружия | Детерминированные логи (6.2), список fail-fast (6.3), тестовые базлайны (6.4) |
| Словарь старта | У отсутствия каждой строки лога есть ясная диагностическая ветвь |
| Fail-fast | 21 кейс конфигурации называют поле и завершаются — работать «с дефектом» нельзя |
| Остановка | Пять фаз без демонтажа; внешний тайм-аут — от сервис-менеджера |
| Отладка памяти | Система отладки памяти xrt (канарейки / UAF / отчёты), ссылки в учебник xrt |
- учебник xrt · отладка памяти — полное применение канареек / изоляции UAF / инъекции отказов / отчётов об утечках
- справочник xrt · logger — API структурного логирования (вместо голого printf)