Files
zhamao-framework/src/ZM/Process/ProcessStateManager.php
crazywhalecc 3a57294e48 fix: add SIGHUP/SIGTERM handling, modernize PHP support and CI
Signal handling fixes:
- SignalListener: add SIGHUP/SIGTERM handling for both Swoole
  and Workerman drivers in master and worker processes
- Prevent 100% CPU when IDE terminal is closed by ensuring
  graceful shutdown on terminal hangup

PHP version support:
- Widen PHP constraint to 8.3, 8.4, 8.5
- Bump doctrine/dbal from ^2.13.1 to ^4.4
- Bump php-cs-fixer to ^3.64, phpstan to ^1.12
- Bump swoole/ide-helper to ^5.0
- Drop phpunit ^8.5 (EOL), keep ^9.0

CI updates:
- actions/checkout@v3 → @v4 (Node.js 20 deprecated)
- Bump static analysis/code style PHP from 8.1 to 8.3
2026-06-17 15:19:00 +08:00

172 lines
6.1 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace ZM\Process;
use OneBot\Driver\Process\ProcessManager;
use ZM\Exception\ZMKnownException;
use ZM\Store\FileSystem;
class ProcessStateManager
{
public static array $process_mode = [];
/**
* 查看是否为多 Worker 模式,插件可能用得到
*/
public static function isMultiWorkers(): bool
{
return (self::$process_mode['worker'] ?? 1) > 1;
}
public static function isTaskWorker(): bool
{
return (ProcessManager::getProcessType() & ONEBOT_PROCESS_TASKWORKER) !== 0;
}
/**
* 删除进程运行状态
*
* @throws ZMKnownException
* @internal
*/
public static function removeProcessState(int $type, int|string|null $id_or_name = null): void
{
switch ($type) {
case ZM_PROCESS_MASTER:
$file = zm_dir(ZM_STATE_DIR . '/master.json');
if (file_exists($file)) {
unlink($file);
}
return;
case ZM_PROCESS_MANAGER:
$file = zm_dir(ZM_STATE_DIR . '/manager.pid');
if (file_exists($file)) {
unlink($file);
}
return;
case ZM_PROCESS_WORKER:
if (!is_int($id_or_name)) {
throw new ZMKnownException('E99999', 'worker_id必须为整数');
}
$file = zm_dir(ZM_STATE_DIR . '/worker.' . $id_or_name . '.pid');
if (file_exists($file)) {
unlink($file);
}
return;
case ZM_PROCESS_USER:
if (!is_string($id_or_name)) {
throw new ZMKnownException('E99999', 'process_name必须为字符串');
}
$file = zm_dir(ZM_STATE_DIR . '/user.' . $id_or_name . '.pid');
if (file_exists($file)) {
unlink($file);
}
return;
case ZM_PROCESS_TASKWORKER:
if (!is_int($id_or_name)) {
throw new ZMKnownException('E99999', 'worker_id必须为整数');
}
$file = zm_dir(ZM_STATE_DIR . '/taskworker.' . $id_or_name . '.pid');
if (file_exists($file)) {
unlink($file);
}
return;
}
}
/**
* 用于框架内部获取多进程运行状态的函数
*
* @return false|int|mixed
* @throws ZMKnownException
* @internal
*/
public static function getProcessState(int $type, mixed $id_or_name = null): mixed
{
$file = ZM_STATE_DIR;
switch ($type) {
case ZM_PROCESS_MASTER:
if (!file_exists(zm_dir($file . '/master.json'))) {
return false;
}
$json = json_decode(file_get_contents(zm_dir($file . '/master.json')), true);
return $json ?? false;
case ZM_PROCESS_MANAGER:
if (!file_exists(zm_dir($file . '/manager.pid'))) {
return false;
}
return intval(file_get_contents(zm_dir($file . '/manager.pid')));
case ZM_PROCESS_WORKER:
if (!is_int($id_or_name)) {
throw new ZMKnownException('E99999', 'worker_id必须为整数');
}
if (!file_exists(zm_dir($file . '/worker.' . $id_or_name . '.pid'))) {
return false;
}
return intval(file_get_contents(zm_dir($file . '/worker.' . $id_or_name . '.pid')));
case ZM_PROCESS_USER:
if (!is_string($id_or_name)) {
throw new ZMKnownException('E99999', 'process_name必须为字符串');
}
if (!file_exists(zm_dir($file . '/user.' . $id_or_name . '.pid'))) {
return false;
}
return intval(file_get_contents(zm_dir($file . '/user.' . $id_or_name . '.pid')));
case ZM_PROCESS_TASKWORKER:
if (!is_int($id_or_name)) {
throw new ZMKnownException('E99999', 'worker_id必须为整数');
}
if (!file_exists(zm_dir($file . '/taskworker.' . $id_or_name . '.pid'))) {
return false;
}
return intval(file_get_contents(zm_dir($file . '/taskworker.' . $id_or_name . '.pid')));
default:
return false;
}
}
/**
* 将各进程的pid写入文件以备后续崩溃及僵尸进程处理使用
*
* @internal
*/
public static function saveProcessState(int $type, int|string $pid, array $data = []): void
{
switch ($type) {
case ZM_PROCESS_MASTER:
$file = zm_dir(ZM_STATE_DIR . '/master.json');
$json = [
'pid' => intval($pid),
'stdout' => $data['stdout'],
'daemon' => $data['daemon'],
];
file_put_contents($file, json_encode($json, JSON_UNESCAPED_UNICODE));
return;
case ZM_PROCESS_MANAGER:
$file = zm_dir(ZM_STATE_DIR . '/manager.pid');
file_put_contents($file, strval($pid));
return;
case ZM_PROCESS_WORKER:
$file = zm_dir(ZM_STATE_DIR . '/worker.' . $data['worker_id'] . '.pid');
file_put_contents($file, strval($pid));
return;
case ZM_PROCESS_USER:
$file = zm_dir(ZM_STATE_DIR . '/user.' . $data['process_name'] . '.pid');
file_put_contents($file, strval($pid));
return;
case ZM_PROCESS_TASKWORKER:
$file = zm_dir(ZM_STATE_DIR . '/taskworker.' . $data['worker_id'] . '.pid');
file_put_contents($file, strval($pid));
return;
}
}
public static function isStateEmpty(): bool
{
$ls = FileSystem::scanDirFiles(ZM_STATE_DIR, false, true);
return empty($ls);
}
}