|
@@ -279,9 +279,9 @@ class Worker
|
|
|
/**
|
|
/**
|
|
|
* Log file.
|
|
* Log file.
|
|
|
*
|
|
*
|
|
|
- * @var mixed
|
|
|
|
|
|
|
+ * @var string
|
|
|
*/
|
|
*/
|
|
|
- public static mixed $logFile = '';
|
|
|
|
|
|
|
+ public static string $logFile;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* Global event loop.
|
|
* Global event loop.
|
|
@@ -314,9 +314,9 @@ class Worker
|
|
|
/**
|
|
/**
|
|
|
* EventLoopClass
|
|
* EventLoopClass
|
|
|
*
|
|
*
|
|
|
- * @var string|class-string
|
|
|
|
|
|
|
+ * @var class-string<EventInterface>
|
|
|
*/
|
|
*/
|
|
|
- public static string $eventLoopClass = '';
|
|
|
|
|
|
|
+ public static string $eventLoopClass;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* After sending the stop command to the child process stopTimeout seconds,
|
|
* After sending the stop command to the child process stopTimeout seconds,
|
|
@@ -486,15 +486,6 @@ class Worker
|
|
|
];
|
|
];
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * Available event loops.
|
|
|
|
|
- *
|
|
|
|
|
- * @var array<string, string>
|
|
|
|
|
- */
|
|
|
|
|
- protected static array $availableEventLoops = [
|
|
|
|
|
- 'event' => Event::class,
|
|
|
|
|
- ];
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
* PHP built-in protocols.
|
|
* PHP built-in protocols.
|
|
|
*
|
|
*
|
|
|
* @var array<string, string>
|
|
* @var array<string, string>
|
|
@@ -563,19 +554,23 @@ class Worker
|
|
|
*/
|
|
*/
|
|
|
public static function runAll(): void
|
|
public static function runAll(): void
|
|
|
{
|
|
{
|
|
|
- static::checkSapiEnv();
|
|
|
|
|
- static::init();
|
|
|
|
|
- static::parseCommand();
|
|
|
|
|
- static::lock();
|
|
|
|
|
- static::daemonize();
|
|
|
|
|
- static::initWorkers();
|
|
|
|
|
- static::installSignal();
|
|
|
|
|
- static::saveMasterPid();
|
|
|
|
|
- static::lock(LOCK_UN);
|
|
|
|
|
- static::displayUI();
|
|
|
|
|
- static::forkWorkers();
|
|
|
|
|
- static::resetStd();
|
|
|
|
|
- static::monitorWorkers();
|
|
|
|
|
|
|
+ try {
|
|
|
|
|
+ static::checkSapiEnv();
|
|
|
|
|
+ static::init();
|
|
|
|
|
+ static::parseCommand();
|
|
|
|
|
+ static::lock();
|
|
|
|
|
+ static::daemonize();
|
|
|
|
|
+ static::initWorkers();
|
|
|
|
|
+ static::installSignal();
|
|
|
|
|
+ static::saveMasterPid();
|
|
|
|
|
+ static::lock(LOCK_UN);
|
|
|
|
|
+ static::displayUI();
|
|
|
|
|
+ static::forkWorkers();
|
|
|
|
|
+ static::resetStd();
|
|
|
|
|
+ static::monitorWorkers();
|
|
|
|
|
+ } catch (\Throwable $e) {
|
|
|
|
|
+ static::log($e);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -587,7 +582,7 @@ class Worker
|
|
|
{
|
|
{
|
|
|
// Only for cli and micro.
|
|
// Only for cli and micro.
|
|
|
if (!in_array(\PHP_SAPI, ['cli', 'micro'])) {
|
|
if (!in_array(\PHP_SAPI, ['cli', 'micro'])) {
|
|
|
- exit("Only run in command line mode\n");
|
|
|
|
|
|
|
+ throw new \RuntimeException("Only run in command line mode");
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -631,8 +626,8 @@ class Worker
|
|
|
// State.
|
|
// State.
|
|
|
static::$status = static::STATUS_STARTING;
|
|
static::$status = static::STATUS_STARTING;
|
|
|
|
|
|
|
|
- // Avoiding incorrect user calls.
|
|
|
|
|
- static::resetGlobalEvent();
|
|
|
|
|
|
|
+ // Init global event.
|
|
|
|
|
+ static::initGlobalEvent();
|
|
|
|
|
|
|
|
// For statistics.
|
|
// For statistics.
|
|
|
static::$globalStatistics['start_timestamp'] = time();
|
|
static::$globalStatistics['start_timestamp'] = time();
|
|
@@ -648,16 +643,30 @@ class Worker
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * reset globalEvent Instance.
|
|
|
|
|
|
|
+ * Init global event.
|
|
|
*
|
|
*
|
|
|
* @return void
|
|
* @return void
|
|
|
*/
|
|
*/
|
|
|
- protected static function resetGlobalEvent(): void
|
|
|
|
|
|
|
+ protected static function initGlobalEvent(): void
|
|
|
{
|
|
{
|
|
|
- if (static::$status === static::STATUS_STARTING && static::$globalEvent instanceof EventInterface) {
|
|
|
|
|
|
|
+ if (static::$globalEvent !== null) {
|
|
|
static::$eventLoopClass = get_class(static::$globalEvent);
|
|
static::$eventLoopClass = get_class(static::$globalEvent);
|
|
|
static::$globalEvent = null;
|
|
static::$globalEvent = null;
|
|
|
|
|
+ return;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ if (isset(static::$eventLoopClass)) {
|
|
|
|
|
+ if (!is_subclass_of(static::$eventLoopClass, EventInterface::class)) {
|
|
|
|
|
+ throw new RuntimeException(sprintf('%s::$eventLoopClass must implement %s', static::class, EventInterface::class));
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ static::$eventLoopClass = match (true) {
|
|
|
|
|
+ class_exists(EventLoop::class) => Revolt::class,
|
|
|
|
|
+ extension_loaded('event') => Event::class,
|
|
|
|
|
+ default => Select::class,
|
|
|
|
|
+ };
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -1333,32 +1342,10 @@ class Worker
|
|
|
/**
|
|
/**
|
|
|
* Get event loop name.
|
|
* Get event loop name.
|
|
|
*
|
|
*
|
|
|
- * @return string
|
|
|
|
|
|
|
+ * @return class-string<EventInterface>
|
|
|
*/
|
|
*/
|
|
|
protected static function getEventLoopName(): string
|
|
protected static function getEventLoopName(): string
|
|
|
{
|
|
{
|
|
|
- if (static::$eventLoopClass) {
|
|
|
|
|
- return static::$eventLoopClass;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (class_exists(EventLoop::class)) {
|
|
|
|
|
- static::$eventLoopClass = Revolt::class;
|
|
|
|
|
- return static::$eventLoopClass;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- $loopName = '';
|
|
|
|
|
- foreach (static::$availableEventLoops as $name => $class) {
|
|
|
|
|
- if (extension_loaded($name)) {
|
|
|
|
|
- $loopName = $name;
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if ($loopName) {
|
|
|
|
|
- static::$eventLoopClass = static::$availableEventLoops[$loopName];
|
|
|
|
|
- } else {
|
|
|
|
|
- static::$eventLoopClass = Select::class;
|
|
|
|
|
- }
|
|
|
|
|
return static::$eventLoopClass;
|
|
return static::$eventLoopClass;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1448,9 +1435,9 @@ class Worker
|
|
|
register_shutdown_function(static::checkErrors(...));
|
|
register_shutdown_function(static::checkErrors(...));
|
|
|
|
|
|
|
|
// Create a global event loop.
|
|
// Create a global event loop.
|
|
|
- if (!static::$globalEvent) {
|
|
|
|
|
|
|
+ if (static::$globalEvent === null) {
|
|
|
$eventLoopClass = static::getEventLoopName();
|
|
$eventLoopClass = static::getEventLoopName();
|
|
|
- static::$globalEvent = new $eventLoopClass;
|
|
|
|
|
|
|
+ static::$globalEvent = new $eventLoopClass();
|
|
|
static::$globalEvent->setErrorHandler(function ($exception) {
|
|
static::$globalEvent->setErrorHandler(function ($exception) {
|
|
|
static::stopAll(250, $exception);
|
|
static::stopAll(250, $exception);
|
|
|
});
|
|
});
|
|
@@ -1518,7 +1505,7 @@ class Worker
|
|
|
$pipes = [];
|
|
$pipes = [];
|
|
|
$process = proc_open('"' . PHP_BINARY . '" ' . " \"$startFile\" -q", $descriptorSpec, $pipes, null, null, ['bypass_shell' => true]);
|
|
$process = proc_open('"' . PHP_BINARY . '" ' . " \"$startFile\" -q", $descriptorSpec, $pipes, null, null, ['bypass_shell' => true]);
|
|
|
|
|
|
|
|
- if (empty(static::$globalEvent)) {
|
|
|
|
|
|
|
+ if (static::$globalEvent === null) {
|
|
|
static::$globalEvent = new Select();
|
|
static::$globalEvent = new Select();
|
|
|
static::$globalEvent->setErrorHandler(function ($exception) {
|
|
static::$globalEvent->setErrorHandler(function ($exception) {
|
|
|
static::stopAll(250, $exception);
|
|
static::stopAll(250, $exception);
|
|
@@ -1589,9 +1576,9 @@ class Worker
|
|
|
register_shutdown_function(static::checkErrors(...));
|
|
register_shutdown_function(static::checkErrors(...));
|
|
|
|
|
|
|
|
// Create a global event loop.
|
|
// Create a global event loop.
|
|
|
- if (!static::$globalEvent) {
|
|
|
|
|
|
|
+ if (static::$globalEvent === null) {
|
|
|
$eventLoopClass = static::getEventLoopName();
|
|
$eventLoopClass = static::getEventLoopName();
|
|
|
- static::$globalEvent = new $eventLoopClass;
|
|
|
|
|
|
|
+ static::$globalEvent = new $eventLoopClass();
|
|
|
static::$globalEvent->setErrorHandler(function ($exception) {
|
|
static::$globalEvent->setErrorHandler(function ($exception) {
|
|
|
static::stopAll(250, $exception);
|
|
static::stopAll(250, $exception);
|
|
|
});
|
|
});
|
|
@@ -1799,7 +1786,7 @@ class Worker
|
|
|
@unlink(static::$pidFile);
|
|
@unlink(static::$pidFile);
|
|
|
static::log("Workerman[" . basename(static::$startFile) . "] has been stopped");
|
|
static::log("Workerman[" . basename(static::$startFile) . "] has been stopped");
|
|
|
if (static::$onMasterStop) {
|
|
if (static::$onMasterStop) {
|
|
|
- call_user_func(static::$onMasterStop);
|
|
|
|
|
|
|
+ (static::$onMasterStop)();
|
|
|
}
|
|
}
|
|
|
exit(0);
|
|
exit(0);
|
|
|
}
|
|
}
|
|
@@ -1824,7 +1811,7 @@ class Worker
|
|
|
// Try to emit onMasterReload callback.
|
|
// Try to emit onMasterReload callback.
|
|
|
if (static::$onMasterReload) {
|
|
if (static::$onMasterReload) {
|
|
|
try {
|
|
try {
|
|
|
- call_user_func(static::$onMasterReload);
|
|
|
|
|
|
|
+ (static::$onMasterReload)();
|
|
|
} catch (Throwable $e) {
|
|
} catch (Throwable $e) {
|
|
|
static::stopAll(250, $e);
|
|
static::stopAll(250, $e);
|
|
|
}
|
|
}
|
|
@@ -1868,7 +1855,7 @@ class Worker
|
|
|
// Try to emit onWorkerReload callback.
|
|
// Try to emit onWorkerReload callback.
|
|
|
if ($worker->onWorkerReload) {
|
|
if ($worker->onWorkerReload) {
|
|
|
try {
|
|
try {
|
|
|
- call_user_func($worker->onWorkerReload, $worker);
|
|
|
|
|
|
|
+ ($worker->onWorkerReload)($worker);
|
|
|
} catch (Throwable $e) {
|
|
} catch (Throwable $e) {
|
|
|
static::stopAll(250, $e);
|
|
static::stopAll(250, $e);
|
|
|
}
|
|
}
|
|
@@ -2166,18 +2153,22 @@ class Worker
|
|
|
/**
|
|
/**
|
|
|
* Log.
|
|
* Log.
|
|
|
*
|
|
*
|
|
|
- * @param mixed $msg
|
|
|
|
|
|
|
+ * @param \Stringable|string $msg
|
|
|
* @param bool $decorated
|
|
* @param bool $decorated
|
|
|
* @return void
|
|
* @return void
|
|
|
*/
|
|
*/
|
|
|
- public static function log(mixed $msg, bool $decorated = false): void
|
|
|
|
|
|
|
+ public static function log(\Stringable|string $msg, bool $decorated = false): void
|
|
|
{
|
|
{
|
|
|
- $msg .= "\n";
|
|
|
|
|
|
|
+ $msg = trim((string)$msg);
|
|
|
|
|
+
|
|
|
if (!static::$daemonize) {
|
|
if (!static::$daemonize) {
|
|
|
- static::safeEcho($msg, $decorated);
|
|
|
|
|
|
|
+ static::safeEcho("$msg\n", $decorated);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (isset(static::$logFile)) {
|
|
|
|
|
+ $pid = DIRECTORY_SEPARATOR === '/' ? posix_getpid() : 1;
|
|
|
|
|
+ file_put_contents(static::$logFile, sprintf("%s pid:%d %s\n", date('Y-m-d H:i:s'), $pid, $msg), FILE_APPEND | LOCK_EX);
|
|
|
}
|
|
}
|
|
|
- file_put_contents(static::$logFile, date('Y-m-d H:i:s') . ' ' . 'pid:'
|
|
|
|
|
- . (DIRECTORY_SEPARATOR === '/' ? posix_getpid() : 1) . ' ' . $msg, FILE_APPEND | LOCK_EX);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -2401,7 +2392,7 @@ class Worker
|
|
|
*/
|
|
*/
|
|
|
public function pauseAccept(): void
|
|
public function pauseAccept(): void
|
|
|
{
|
|
{
|
|
|
- if (static::$globalEvent && false === $this->pauseAccept && $this->mainSocket) {
|
|
|
|
|
|
|
+ if (static::$globalEvent !== null && $this->pauseAccept === false && $this->mainSocket !== null) {
|
|
|
static::$globalEvent->offReadable($this->mainSocket);
|
|
static::$globalEvent->offReadable($this->mainSocket);
|
|
|
$this->pauseAccept = true;
|
|
$this->pauseAccept = true;
|
|
|
}
|
|
}
|
|
@@ -2415,7 +2406,7 @@ class Worker
|
|
|
public function resumeAccept(): void
|
|
public function resumeAccept(): void
|
|
|
{
|
|
{
|
|
|
// Register a listener to be notified when server socket is ready to read.
|
|
// Register a listener to be notified when server socket is ready to read.
|
|
|
- if (static::$globalEvent && true === $this->pauseAccept && $this->mainSocket) {
|
|
|
|
|
|
|
+ if (static::$globalEvent !== null && $this->pauseAccept === true && $this->mainSocket !== null) {
|
|
|
if ($this->transport !== 'udp') {
|
|
if ($this->transport !== 'udp') {
|
|
|
static::$globalEvent->onReadable($this->mainSocket, $this->acceptTcpConnection(...));
|
|
static::$globalEvent->onReadable($this->mainSocket, $this->acceptTcpConnection(...));
|
|
|
} else {
|
|
} else {
|