mirror of
https://github.com/Vateron-Media/XC_VM.git
synced 2026-10-25 19:03:14 +01:00
A connection row records the PHP-FPM worker serving it (getmypid() in live.php, vod.php and timeshift.php), but the watchdog published as servers.php_pids the contents of bin/php/sockets/*.pid: the FPM master pids. In Redis mode MAIN's cron:users reaps every node's connections and, for a remote PHP-served connection older than the node's last heartbeat, checks the worker pid against that list. It never matched, so the connection was closed and the LB told to kill its worker: every VOD, timeshift and PHP-served live viewer on an LB was dropped about a minute after connecting. MySQL mode was unaffected (each node probes its own pids locally). - ProcessManager::phpFpmWorkerPIDs() lists the processes titled "php-fpm: pool xc_vm" (sorted, unique); findProcessPIDs() takes an optional procfs root so it can run against a fixture tree. - WatchdogCommand publishes that list instead of the pid files. - ServerRepository::getAll() drops php_pids from the rows it returns and caches, so the per-request servers cache does not carry every node's worker list. CacheCronJob's unset($rServers['php_pids']) meant to do that but hit a top-level key of an id-keyed map; it is removed. - UsersCronJob reads php_pids with its own SELECT `id`, `php_pids`. The `- 1` heartbeat margin is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TQHeypQpfAXTdCysmi7b6a
66 lines
2.5 KiB
PHP
66 lines
2.5 KiB
PHP
<?php
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
use XcVm\Core\Process\ProcessManager;
|
|
|
|
/**
|
|
* ProcessManager::phpFpmWorkerPIDs — the pid list the watchdog publishes as
|
|
* servers.php_pids. A connection row's pid is the PHP-FPM worker serving it
|
|
* (getmypid() in live/vod/timeshift), so the list must hold the workers of
|
|
* the xc_vm pool. It used to hold the FPM master pids from the pool pid files,
|
|
* which never match a worker: in Redis mode MAIN's cron:users then closed
|
|
* every PHP-served LB viewer about a minute after it connected.
|
|
*
|
|
* Driven against a fixture /proc tree. Its pids are above the kernel's
|
|
* PID_MAX_LIMIT (4194304), so none can be this process's own pid, which
|
|
* findProcessPIDs() skips.
|
|
*/
|
|
final class PhpFpmWorkerPidsTest extends TestCase {
|
|
|
|
private string $rRoot;
|
|
|
|
protected function setUp(): void {
|
|
$this->rRoot = sys_get_temp_dir() . '/xcvm_proc_' . uniqid('', true);
|
|
mkdir($this->rRoot, 0755, true);
|
|
}
|
|
|
|
protected function tearDown(): void {
|
|
foreach (glob($this->rRoot . '/*/cmdline') ?: [] as $rFile) {
|
|
unlink($rFile);
|
|
rmdir(dirname($rFile));
|
|
}
|
|
@rmdir($this->rRoot);
|
|
}
|
|
|
|
private function process(int $rPID, string $rCmdline): void {
|
|
mkdir($this->rRoot . '/' . $rPID);
|
|
file_put_contents($this->rRoot . '/' . $rPID . '/cmdline', $rCmdline);
|
|
}
|
|
|
|
public function testListsTheXcVmPoolWorkersOnly(): void {
|
|
$this->process(4300001, "php-fpm: master process (/home/xc_vm/bin/php/etc/1.conf)\0");
|
|
// FPM overwrites the worker's argv with its title and pads the rest with NULs.
|
|
$this->process(4300002, 'php-fpm: pool xc_vm' . str_repeat("\0", 40));
|
|
$this->process(4300003, 'php-fpm: pool xc_vm');
|
|
$this->process(4300004, "/home/xc_vm/bin/php/bin/php\0console.php\0watchdog\0");
|
|
$this->process(4300005, 'php-fpm: pool www');
|
|
// Globbed before 4300002 (string order); listed after it (numeric order).
|
|
$this->process(43000040, 'php-fpm: pool xc_vm');
|
|
|
|
$this->assertSame([4300002, 4300003, 43000040], ProcessManager::phpFpmWorkerPIDs($this->rRoot));
|
|
}
|
|
|
|
public function testNoWorkersYieldsAnEmptyList(): void {
|
|
$this->process(4300001, "php-fpm: master process (/home/xc_vm/bin/php/etc/1.conf)\0");
|
|
|
|
$this->assertSame([], ProcessManager::phpFpmWorkerPIDs($this->rRoot));
|
|
}
|
|
|
|
public function testFindProcessPIDsReadsTheGivenProcRoot(): void {
|
|
$this->assertSame([], ProcessManager::findProcessPIDs(['x'], 0, $this->rRoot));
|
|
|
|
$this->process(4300007, "ffmpeg\0-i\0x\0");
|
|
$this->assertSame([4300007], ProcessManager::findProcessPIDs(['ffmpeg'], 0, $this->rRoot));
|
|
}
|
|
}
|