Files
kiri-http-server/Abstracts/ReloadWorkers.php
T

158 lines
3.2 KiB
PHP
Raw Normal View History

2026-07-08 11:58:04 +08:00
<?php
namespace Kiri\Server\Abstracts;
2026-07-15 09:52:12 +08:00
use Kiri\Server\ServerInterface;
2026-07-08 11:58:04 +08:00
use Swoole\Process;
trait ReloadWorkers
{
2026-07-10 15:57:44 +08:00
private static ?int $cachedMasterPid = null;
2026-07-08 11:58:04 +08:00
/**
* @return void
*/
private function reloadWorkers(): bool
{
2026-07-15 09:42:08 +08:00
if ($this->reloadByServerInstance()) {
return true;
}
2026-07-08 11:58:04 +08:00
$pid = $this->getMasterPid();
if ($pid === null) {
return false;
}
return Process::kill($pid, SIGUSR1);
}
2026-07-15 09:42:08 +08:00
private function reloadByServerInstance(): bool
{
try {
2026-07-15 09:52:12 +08:00
$server = di(ServerInterface::class) ;
2026-07-15 09:42:08 +08:00
return $server->reload() !== false;
} catch (\Throwable) {
return false;
}
}
2026-07-08 11:58:04 +08:00
private function getMasterPid(): ?int
{
2026-07-10 15:57:44 +08:00
if (self::$cachedMasterPid !== null && $this->isCachedMasterPid(self::$cachedMasterPid)) {
return self::$cachedMasterPid;
}
self::$cachedMasterPid = null;
2026-07-14 22:53:12 +08:00
$pidFilePid = $this->getPidFileMasterPid();
if ($pidFilePid !== null) {
self::$cachedMasterPid = $pidFilePid;
return $pidFilePid;
}
2026-07-08 11:58:04 +08:00
$processes = $this->listProcesses();
$candidates = [];
foreach ($processes as $process) {
if ($this->isMasterProcessCommand($process['command'])) {
$candidates[] = (int)$process['pid'];
}
}
foreach ($candidates
|> array_filter(...)
|> array_unique(...)
|> array_values(...) as $pid) {
if ($this->isProcessAlive($pid) && $this->isMasterPid($pid, $processes)) {
2026-07-10 15:57:44 +08:00
self::$cachedMasterPid = $pid;
2026-07-08 11:58:04 +08:00
return $pid;
}
}
return null;
}
2026-07-10 15:57:44 +08:00
private function isCachedMasterPid(int $pid): bool
{
if (!$this->isProcessAlive($pid)) {
return false;
}
2026-07-14 22:53:12 +08:00
$pidFilePid = $this->readPidFile();
if ($pidFilePid === $pid && $this->isSameAppProcess($pid)) {
return true;
}
2026-07-10 15:57:44 +08:00
$command = $this->readProcessCommand($pid);
return $command !== '' && $this->isMasterProcessCommand($command) && $this->isSameAppProcess($pid);
}
2026-07-14 22:53:12 +08:00
private function getPidFileMasterPid(): ?int
{
$pid = $this->readPidFile();
if ($pid === null || !$this->isProcessAlive($pid) || !$this->isSameAppProcess($pid)) {
return null;
}
return $pid;
}
private function readPidFile(): ?int
{
$pidFile = function_exists('storage') ? storage('.swoole.pid') : '';
if ($pidFile === '' || !is_file($pidFile)) {
return null;
}
$pid = (int)trim((string)file_get_contents($pidFile));
return $pid > 1 ? $pid : null;
}
2026-07-10 15:57:44 +08:00
private function readProcessCommand(int $pid): string
{
$cmdline = @file_get_contents('/proc/' . $pid . '/cmdline');
if (is_string($cmdline) && $cmdline !== '') {
return trim(str_replace("\0", ' ', $cmdline));
}
return '';
}
2026-07-08 11:58:04 +08:00
private function isMasterPid(int $pid, array $processes): bool
{
foreach ($processes as $process) {
if ((int)$process['pid'] === $pid) {
return $this->isMasterProcessCommand($process['command']) && $this->isSameAppProcess($pid);
}
}
return false;
}
private function listProcesses(): array
{
$lines = [];
2026-07-14 22:53:12 +08:00
exec('ps -eo pid=,ppid=,args= 2>/dev/null', $lines);
2026-07-08 11:58:04 +08:00
$processes = [];
foreach ($lines as $line) {
$line = trim($line);
if ($line === '') {
continue;
}
$parts = preg_split('/\s+/', $line, 3);
if (count($parts) < 3) {
continue;
}
$processes[] = [
'pid' => (int)$parts[0],
'ppid' => (int)$parts[1],
'command' => $parts[2],
];
}
return $processes;
}
}