Browse Source

Merge branch 'master' into events_finalize

Anton 2 years ago
parent
commit
32112b1469
6 changed files with 78 additions and 90 deletions
  1. 0 3
      phpstan.neon.dist
  2. 3 2
      src/Connection/TcpConnection.php
  3. 1 1
      src/Events/Revolt.php
  4. 2 0
      src/Events/Swow.php
  5. 72 80
      src/Worker.php
  6. 0 4
      tests/Pest.php

+ 0 - 3
phpstan.neon.dist

@@ -32,8 +32,5 @@ parameters:
 	            - '#Call to an undefined method EventBase::+.#'
 	    - path: src/Timer.php
 	      message: '#Call to static method getSuspension\(\) on an unknown class Revolt\\EventLoop.#'
-	    - path: tests/Pest.php
-	      message: '#Undefined variable: \$this#'
 	    - path: src/Worker.php
 	      message: '#Constant LINE_VERSION_LENGTH not found.#'
-	    - message: '#Parameter \#1 \$callback of function set_error_handler expects \(callable\(int, string, string, int\): bool\)\|null,.*#'

+ 3 - 2
src/Connection/TcpConnection.php

@@ -816,10 +816,11 @@ class TcpConnection extends ConnectionInterface implements JsonSerializable
         }
 
         // Hidden error.
-        set_error_handler(function ($errno, $err_str) {
+        set_error_handler(static function (int $code, string $msg): bool {
             if (!Worker::$daemonize) {
-                Worker::safeEcho("SSL handshake error: $err_str \n");
+                Worker::safeEcho(sprintf("SSL handshake error: %s\n", $msg));
             }
+            return true;
         });
         $ret = stream_socket_enable_crypto($socket, true, $type);
         restore_error_handler();

+ 1 - 1
src/Events/Revolt.php

@@ -113,7 +113,7 @@ final class Revolt implements EventInterface
     public function delay(float $delay, callable $func, array $args = []): int
     {
         $timerId = $this->timerId++;
-        $closure = static function () use ($func, $args, $timerId) {
+        $closure = function () use ($func, $args, $timerId) {
             unset($this->eventTimer[$timerId]);
             $func(...$args);
         };

+ 2 - 0
src/Events/Swow.php

@@ -27,12 +27,14 @@ final class Swow implements EventInterface
 
     /**
      * All listeners for write event.
+     *
      * @var array<int, Coroutine>
      */
     private array $writeEvents = [];
 
     /**
      * All listeners for signal.
+     *
      * @var array<int, Coroutine>
      */
     private array $signalListener = [];

+ 72 - 80
src/Worker.php

@@ -279,9 +279,9 @@ class Worker
     /**
      * Log file.
      *
-     * @var mixed
+     * @var string
      */
-    public static mixed $logFile = '';
+    public static string $logFile;
 
     /**
      * Global event loop.
@@ -314,9 +314,9 @@ class Worker
     /**
      * 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,
@@ -486,15 +486,6 @@ class Worker
     ];
 
     /**
-     * Available event loops.
-     *
-     * @var array<string, string>
-     */
-    protected static array $availableEventLoops = [
-        'event' => Event::class,
-    ];
-
-    /**
      * PHP built-in protocols.
      *
      * @var array<string, string>
@@ -563,19 +554,23 @@ class Worker
      */
     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.
         if (!in_array(\PHP_SAPI, ['cli', 'micro'])) {
-            exit("Only run in command line mode\n");
+            throw new \RuntimeException("Only run in command line mode");
         }
     }
 
@@ -598,8 +593,9 @@ class Worker
      */
     protected static function init(): void
     {
-        set_error_handler(function ($code, $msg, $file, $line) {
-            static::safeEcho("$msg in file $file on line $line\n");
+        set_error_handler(static function (int $code, string $msg, string $file, int $line): bool {
+            static::safeEcho(sprintf("%s \"%s\" in file %s on line %d\n", static::getErrorType($code), $msg, $file, $line));
+            return true;
         });
 
         // Start file.
@@ -630,8 +626,8 @@ class Worker
         // State.
         static::$status = static::STATUS_STARTING;
 
-        // Avoiding incorrect user calls.
-        static::resetGlobalEvent();
+        // Init global event.
+        static::initGlobalEvent();
 
         // For statistics.
         static::$globalStatistics['start_timestamp'] = time();
@@ -647,16 +643,30 @@ class Worker
     }
 
     /**
-     * reset globalEvent Instance.
+     * Init global event.
      *
      * @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::$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,
+        };
     }
 
     /**
@@ -1280,7 +1290,7 @@ class Worker
         $handle = fopen(static::$stdoutFile, "a");
         if ($handle) {
             unset($handle);
-            set_error_handler(function () {});
+            set_error_handler(static fn (): bool => true);
             if ($STDOUT) {
                 fclose($STDOUT);
             }
@@ -1332,32 +1342,10 @@ class Worker
     /**
      * Get event loop name.
      *
-     * @return string
+     * @return class-string<EventInterface>
      */
     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;
     }
 
@@ -1447,9 +1435,9 @@ class Worker
             register_shutdown_function(static::checkErrors(...));
 
             // Create a global event loop.
-            if (!static::$globalEvent) {
+            if (static::$globalEvent === null) {
                 $eventLoopClass = static::getEventLoopName();
-                static::$globalEvent = new $eventLoopClass;
+                static::$globalEvent = new $eventLoopClass();
                 static::$globalEvent->setErrorHandler(function ($exception) {
                     static::stopAll(250, $exception);
                 });
@@ -1517,7 +1505,7 @@ class Worker
         $pipes = [];
         $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->setErrorHandler(function ($exception) {
                 static::stopAll(250, $exception);
@@ -1588,9 +1576,9 @@ class Worker
             register_shutdown_function(static::checkErrors(...));
 
             // Create a global event loop.
-            if (!static::$globalEvent) {
+            if (static::$globalEvent === null) {
                 $eventLoopClass = static::getEventLoopName();
-                static::$globalEvent = new $eventLoopClass;
+                static::$globalEvent = new $eventLoopClass();
                 static::$globalEvent->setErrorHandler(function ($exception) {
                     static::stopAll(250, $exception);
                 });
@@ -1675,7 +1663,7 @@ class Worker
      */
     protected static function setProcessTitle(string $title): void
     {
-        set_error_handler(function (){});
+        set_error_handler(static fn (): bool => true);
         cli_set_process_title($title);
         restore_error_handler();
     }
@@ -1798,7 +1786,7 @@ class Worker
         @unlink(static::$pidFile);
         static::log("Workerman[" . basename(static::$startFile) . "] has been stopped");
         if (static::$onMasterStop) {
-            call_user_func(static::$onMasterStop);
+            (static::$onMasterStop)();
         }
         exit(0);
     }
@@ -1823,7 +1811,7 @@ class Worker
                 // Try to emit onMasterReload callback.
                 if (static::$onMasterReload) {
                     try {
-                        call_user_func(static::$onMasterReload);
+                        (static::$onMasterReload)();
                     } catch (Throwable $e) {
                         static::stopAll(250, $e);
                     }
@@ -1867,7 +1855,7 @@ class Worker
             // Try to emit onWorkerReload callback.
             if ($worker->onWorkerReload) {
                 try {
-                    call_user_func($worker->onWorkerReload, $worker);
+                    ($worker->onWorkerReload)($worker);
                 } catch (Throwable $e) {
                     static::stopAll(250, $e);
                 }
@@ -2165,18 +2153,22 @@ class Worker
     /**
      * Log.
      *
-     * @param mixed $msg
+     * @param \Stringable|string $msg
      * @param bool $decorated
      * @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) {
-            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);
     }
 
     /**
@@ -2273,7 +2265,7 @@ class Worker
             $address = \parse_url($socketName);
             if (isset($address['host']) && isset($address['port'])) {
                 try {
-                    \set_error_handler(function(){});
+                    \set_error_handler(static fn (): bool => true);
                     // If address not in use, turn reusePort on automatically.
                     $server = stream_socket_server("tcp://{$address['host']}:{$address['port']}");
                     if ($server) {
@@ -2330,7 +2322,7 @@ class Worker
 
             // Try to open keepalive for tcp and disable Nagle algorithm.
             if (function_exists('socket_import_stream') && self::BUILD_IN_TRANSPORTS[$this->transport] === 'tcp') {
-                set_error_handler(function () {});
+                set_error_handler(static fn (): bool => true);
                 $socket = socket_import_stream($this->mainSocket);
                 socket_set_option($socket, SOL_SOCKET, SO_KEEPALIVE, 1);
                 socket_set_option($socket, SOL_TCP, TCP_NODELAY, 1);
@@ -2353,7 +2345,7 @@ class Worker
     {
         $this->pauseAccept();
         if ($this->mainSocket) {
-            set_error_handler(function () {});
+            set_error_handler(static fn (): bool => true);
             fclose($this->mainSocket);
             restore_error_handler();
             $this->mainSocket = null;
@@ -2400,7 +2392,7 @@ class Worker
      */
     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);
             $this->pauseAccept = true;
         }
@@ -2414,7 +2406,7 @@ class Worker
     public function resumeAccept(): void
     {
         // 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') {
                 static::$globalEvent->onReadable($this->mainSocket, $this->acceptTcpConnection(...));
             } else {
@@ -2504,7 +2496,7 @@ class Worker
     protected function acceptTcpConnection(mixed $socket): void
     {
         // Accept a connection on server socket.
-        set_error_handler(function () {});
+        set_error_handler(static fn (): bool => true);
         $newSocket = stream_socket_accept($socket, 0, $remoteAddress);
         restore_error_handler();
 
@@ -2544,7 +2536,7 @@ class Worker
      */
     protected function acceptUdpConnection(mixed $socket): void
     {
-        set_error_handler(function () {});
+        set_error_handler(static fn (): bool => true);
         $recvBuffer = stream_socket_recvfrom($socket, UdpConnection::MAX_UDP_PACKAGE_SIZE, 0, $remoteAddress);
         restore_error_handler();
         if (false === $recvBuffer || empty($remoteAddress)) {

+ 0 - 4
tests/Pest.php

@@ -26,10 +26,6 @@
 
 use Workerman\Connection\TcpConnection;
 
-expect()->extend('toBeOne', function () {
-    return $this->toBe(1);
-});
-
 /*
 |--------------------------------------------------------------------------
 | Functions