Structure:
- Split development/ (20 files) into development/ (framework reference) and guides/ (how-to)
- Moved 13 how-to files into new guides/ category (auth, cli, error-handling, etc.)
- Moved navbar-rendering.md from system/ into development/
- Deleted empty system/README.md files
- Deleted documentation_gaps.md (all gaps resolved) and redundant info/update.md
Sidebar / navbar:
- Removed all emojis from _sidebar.md (EN + RU) — fixes tree hierarchy rendering
- Removed flag emojis from _navbar.md language switcher
- Removed duplicate entries from the old "System Documentation" section
- Renamed section headers: "Development" -> "Framework Reference" + "Developer Guides"
Content fixes (modules.md EN + RU):
- Updated "Class naming" section: now documents XcVm\Module\{Pascal} namespaces
(was "global PHP namespace — Until PHP namespaces are introduced")
- Updated main module class example to use namespace declaration + use statements
- Updated class naming in ModuleLoader description to FQN
- Replaced installCrontab() manual crontab instruction with getCronEntries() API
- Updated enable/disable section: added ModuleState enum table, updated config examples
- Fixed FAQ answer for disabling a module
Content fixes (bootstrap-contexts.md EN + RU):
- Replaced CONTEXT_* string constants with BootContext enum cases throughout
- Updated boot() signature: string $context -> BootContext $context
- Updated getContext() return type: ?string -> ?BootContext
New framework reference docs (EN + RU):
- docs/{en,ru}/development/event-system.md: EventDispatcher singleton bridge,
#[ListensTo] attribute, getEventSubscribers() array API, stoppable events,
built-in event catalog, custom event authoring, ListensTo attribute reference
- docs/{en,ru}/development/exception-hierarchy.md: full XcVmException tree,
container vs module subtrees, PSR-11 compliance notes, catch-by-subsystem examples
6.0 KiB
Паттерны управления процессами
ProcessManager централизует операции с процессами Linux: проверку активности, завершение и захват cron-блокировок. Заменяет разрозненные вызовы posix_kill(), shell_exec('ps ...') и file_exists('/proc/PID').
Базовые операции
Проверка активности процесса
// Проверить, жив ли процесс
ProcessManager::isRunning(int $pid, ?string $exe = null): bool
- Без
$exe— только проверяет наличие/proc/{pid} - С
$exe— дополнительно проверяет имя исполняемого файла через/proc/{pid}/exe
// Примеры
ProcessManager::isRunning(1234); // процесс жив?
ProcessManager::isRunning(1234, 'ffmpeg'); // это ffmpeg?
ProcessManager::isRunning(1234, PHP_BIN); // это PHP?
Именованный процесс
Для процессов, которые устанавливают заголовок через cli_set_process_title() в формате NAME[ID]:
ProcessManager::isNamedProcessRunning(
int $pid,
string $processName, // 'XC_VM', 'Thumbnail', 'TVArchive'
int|string $identifier, // stream ID
?string $exe = null // ожидаемый исполняемый (по умолч.: PHP_BIN)
): bool
// Проверить, запущен ли PHP-процесс "XC_VM[42]" с PID 5678
ProcessManager::isNamedProcessRunning(5678, 'XC_VM', 42);
Читает /proc/{pid}/cmdline и сравнивает с "NAME[ID]".
Стриминговый процесс
Специализированная проверка для FFmpeg/PHP стриминговых процессов:
ProcessManager::isStreamRunning(int $pid, int $streamId): bool
Логика:
- Если исполняемый файл —
ffmpeg: проверяет cmdline на наличие/{streamId}_.m3u8или/{streamId}_%d.ts - Если исполняемый файл —
php: возвращаетtrue(PHP-стримеры не имеют уникальных аргументов)
PID-файлы
// Проверить процесс по PID-файлу
ProcessManager::checkPidFile(string $pidFile, string $searchString): bool
// Проверить, содержит ли cmdline процесса заданную строку
ProcessManager::matchesCmdline(int $pid, string $search): bool
// Пример cron-задачи
if (ProcessManager::checkPidFile('/tmp/my_cron.pid', 'my_cron_script')) {
// процесс уже запущен
exit(0);
}
Завершение процессов
ProcessManager::kill(int $pid, int $signal = SIGKILL): bool
По умолчанию — SIGKILL (немедленное завершение). Для мягкого завершения:
ProcessManager::kill($pid, SIGTERM); // дать время на завершение
ProcessManager::kill($pid, SIGKILL); // принудительно
Cron-блокировки
Предотвращает параллельный запуск одной и той же cron-задачи.
ProcessManager::acquireCronLock(string $pidFile, int $maxAge = 1800): void
- Если PID-файл существует и процесс ещё жив — завершает текущий скрипт (
exit(0)) - Если PID-файл устарел (старше
$maxAgeсекунд) — удаляет и создаёт новый - Если блокировка захвачена — регистрирует
register_shutdown_functionдля автоматической очистки PID-файла
// Типичное использование в cron-задаче
ProcessManager::acquireCronLock('/tmp/xc_vm/cron_streams.pid', 1800);
// ... дальнейшая работа ...
// PID-файл удаляется автоматически при завершении скрипта
Кеш проверок /proc
isRunning() кеширует результаты проверок /proc/{pid} на 1 секунду ($cacheTtl = 1.0). Это снижает нагрузку при множественных проверках одного PID в рамках одного запроса.
Для принудительного сброса кеша перед критичной проверкой:
clearstatcache(true);
ProcessManager::isNamedProcessRunning($pid, 'XC_VM', $streamId);
Именование процессов
XC_VM использует соглашение NAME[ID] для именования PHP-процессов:
| Имя процесса | Описание |
|---|---|
XC_VM[{id}] |
Основной стриминговый процесс |
Thumbnail[{id}] |
Генерация превью |
TVArchive[{id}] |
TV-архивирование |
Эти имена устанавливаются через cli_set_process_title() в CLI-контексте. Подробнее о CLI-контексте — в Контексты Bootstrap.
Связанные файлы
| Файл | Назначение |
|---|---|
src/core/Process/ProcessManager.php |
Основной класс управления процессами |
src/core/Process/Multithread.php |
Многопоточное выполнение |
src/core/Process/Thread.php |
Обёртка потока |
src/bootstrap.php |
CONTEXT_CLI устанавливает имя процесса |