Browse Source

support Event->setErrorHandler

walkor 2 years ago
parent
commit
3b2c4021d6
8 changed files with 222 additions and 23 deletions
  1. 22 2
      src/Events/Ev.php
  2. 42 3
      src/Events/Event.php
  3. 21 8
      src/Events/EventInterface.php
  4. 16 0
      src/Events/Revolt.php
  5. 36 2
      src/Events/Select.php
  6. 39 5
      src/Events/Swoole.php
  7. 37 3
      src/Events/Swow.php
  8. 9 0
      src/Worker.php

+ 22 - 2
src/Events/Ev.php

@@ -13,8 +13,8 @@
 
 namespace Workerman\Events;
 
-use Workerman\Worker;
-use \EvWatcher;
+use Closure;
+use EvWatcher;
 
 /**
  * Ev eventloop
@@ -50,6 +50,11 @@ class Ev implements EventInterface
     protected $eventTimer = [];
 
     /**
+     * @var Closure || null
+     */
+    protected $errorHandler;
+
+    /**
      * Timer id.
      *
      * @var int
@@ -208,4 +213,19 @@ class Ev implements EventInterface
         return \count($this->eventTimer);
     }
 
+    /**
+     * {@inheritdoc}
+     */
+    public function setErrorHandler($errorHandler)
+    {
+        $this->errorHandler = $errorHandler;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getErrorHandler()
+    {
+        return $this->errorHandler;
+    }
 }

+ 42 - 3
src/Events/Event.php

@@ -14,7 +14,7 @@
 
 namespace Workerman\Events;
 
-use Workerman\Worker;
+use Throwable;
 
 /**
  * libevent eventloop
@@ -65,6 +65,11 @@ class Event implements EventInterface
     protected $eventClassName = '';
 
     /**
+     * @var Closure || null
+     */
+    protected $errorHandler;
+
+    /**
      * Construct.
      * @return void
      */
@@ -95,7 +100,7 @@ class Event implements EventInterface
             try {
                 $func(...$args);
             } catch (\Throwable $e) {
-                Worker::stopAll(250, $e);
+                $this->error($e);
             }
         });
         if (!$event || !$event->addTimer($delay)) {
@@ -137,7 +142,7 @@ class Event implements EventInterface
             try {
                 $func(...$args);
             } catch (\Throwable $e) {
-                Worker::stopAll(250, $e);
+                $this->error($e);
             }
         });
         if (!$event || !$event->addTimer($interval)) {
@@ -262,4 +267,38 @@ class Event implements EventInterface
     {
         return \count($this->eventTimer);
     }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setErrorHandler($errorHandler)
+    {
+        $this->errorHandler = $errorHandler;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getErrorHandler()
+    {
+        return $this->errorHandler;
+    }
+
+    /**
+     * @param Throwable $e
+     * @return void
+     * @throws Throwable
+     */
+    public function error(Throwable $e)
+    {
+        try {
+            if (!$this->errorHandler) {
+                throw new $e;
+            }
+            ($this->errorHandler)($e);
+        } catch (\Throwable $e) {
+            // Cannot trigger an exception in the Event callback, otherwise it will cause an infinite loop
+            echo $e;
+        }
+    }
 }

+ 21 - 8
src/Events/EventInterface.php

@@ -25,6 +25,13 @@ interface EventInterface
     public function delay(float $delay, $func, $args = []);
 
     /**
+     * Delete a delay timer.
+     * @param $timerId
+     * @return bool
+     */
+    public function offDelay($timerId);
+
+    /**
      * Repeatedly execute a callback.
      * @param float $interval
      * @param $func
@@ -34,13 +41,6 @@ interface EventInterface
     public function repeat(float $interval, $func, $args = []);
 
     /**
-     * Delete a delay timer.
-     * @param $timerId
-     * @return bool
-     */
-    public function offDelay($timerId);
-
-    /**
      * Delete a repeat timer.
      * @param $timerId
      * @return bool
@@ -111,8 +111,21 @@ interface EventInterface
     public function stop();
 
     /**
-     * 
+     * Get Timer count.
      * @return int
      */
     public function getTimerCount();
+
+    /**
+     * Set error handler
+     * @param $errorHandler
+     * @return void
+     */
+    public function setErrorHandler($errorHandler);
+
+    /**
+     * Get error handler
+     * @return null|\Closure(\Throwable)
+     */
+    public function getErrorHandler();
 }

+ 16 - 0
src/Events/Revolt.php

@@ -247,4 +247,20 @@ class Revolt implements EventInterface
     {
         return \count($this->eventTimer);
     }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setErrorHandler($errorHandler)
+    {
+        $this->driver->setErrorHandler($errorHandler);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getErrorHandler()
+    {
+        return $this->driver->getErrorHandler();
+    }
 }

+ 36 - 2
src/Events/Select.php

@@ -15,7 +15,6 @@
 namespace Workerman\Events;
 
 use Throwable;
-use Workerman\Worker;
 
 /**
  * select eventloop
@@ -106,6 +105,11 @@ class Select implements EventInterface
     protected $selectTimeout = 100000000;
 
     /**
+     * @var Closure || null
+     */
+    protected $errorHandler;
+
+    /**
      * Construct.
      */
     public function __construct()
@@ -301,7 +305,8 @@ class Select implements EventInterface
                 try {
                     $taskData[0](...$taskData[1]);
                 } catch (Throwable $e) {
-                    Worker::stopAll(250, $e);
+                    $this->error($e);
+                    continue;
                 }
             } else {
                 break;
@@ -405,4 +410,33 @@ class Select implements EventInterface
         return \count($this->eventTimer);
     }
 
+    /**
+     * {@inheritdoc}
+     */
+    public function setErrorHandler($errorHandler)
+    {
+        $this->errorHandler = $errorHandler;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getErrorHandler()
+    {
+        return $this->errorHandler;
+    }
+
+    /**
+     * @param Throwable $e
+     * @return void
+     * @throws Throwable
+     */
+    public function error(Throwable $e)
+    {
+        if (!$this->errorHandler) {
+            throw new $e;
+        }
+        ($this->errorHandler)($e);
+    }
+
 }

+ 39 - 5
src/Events/Swoole.php

@@ -13,7 +13,7 @@
 
 namespace Workerman\Events;
 
-use Workerman\Worker;
+use Throwable;
 use Swoole\Event;
 use Swoole\Timer;
 use Swoole\Process;
@@ -44,6 +44,11 @@ class Swoole implements EventInterface
     protected $mapId = 0;
 
     /**
+     * @var Closure || null
+     */
+    protected $errorHandler;
+
+    /**
      * {@inheritdoc}
      */
     public function delay(float $delay, $func, $args = [])
@@ -54,8 +59,8 @@ class Swoole implements EventInterface
             unset($this->eventTimer[$timerId]);
             try {
                 $func(...(array)$args);
-            } catch (\Throwable $e) {
-                Worker::stopAll(250, $e);
+            } catch (Throwable $e) {
+                $this->error($e);
             }
         });
         $this->eventTimer[$timerId] = $timerId;
@@ -96,8 +101,8 @@ class Swoole implements EventInterface
         $timerId = Timer::tick($t, function () use ($func, $args) {
             try {
                 $func(...(array)$args);
-            } catch (\Throwable $e) {
-                Worker::stopAll(250, $e);
+            } catch (Throwable $e) {
+                $this->error($e);
             }
         });
         $this->eventTimer[$timerId] = $timerId;
@@ -229,4 +234,33 @@ class Swoole implements EventInterface
         return \count($this->eventTimer);
     }
 
+    /**
+     * {@inheritdoc}
+     */
+    public function setErrorHandler($errorHandler)
+    {
+        $this->errorHandler = $errorHandler;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getErrorHandler()
+    {
+        return $this->errorHandler;
+    }
+
+    /**
+     * @param Throwable $e
+     * @return void
+     * @throws Throwable
+     */
+    public function error(Throwable $e)
+    {
+        if (!$this->errorHandler) {
+            throw new $e;
+        }
+        ($this->errorHandler)($e);
+    }
+
 }

+ 37 - 3
src/Events/Swow.php

@@ -6,7 +6,7 @@ use RuntimeException;
 use Swow\Coroutine;
 use Swow\Signal;
 use Swow\SignalException;
-use Workerman\Worker;
+use Throwable;
 use function getmypid;
 use function max;
 use function msleep;
@@ -44,6 +44,11 @@ class Swow implements EventInterface
     protected $signalListener = [];
 
     /**
+     * @var Closure || null
+     */
+    protected $errorHandler;
+
+    /**
      * Get timer count.
      *
      * @return integer
@@ -66,7 +71,7 @@ class Swow implements EventInterface
             try {
                 $func(...(array) $args);
             } catch (\Throwable $e) {
-                Worker::stopAll(250, $e);
+                $this->error($e);
             }
         });
         $timerId = $coroutine->getId();
@@ -87,7 +92,7 @@ class Swow implements EventInterface
                 try {
                     $func(...(array) $args);
                 } catch (\Throwable $e) {
-                    Worker::stopAll(250, $e);
+                    $this->error($e);
                 }
             }
         });
@@ -285,4 +290,33 @@ class Swow implements EventInterface
     {
         waitAll();
     }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setErrorHandler($errorHandler)
+    {
+        $this->errorHandler = $errorHandler;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getErrorHandler()
+    {
+        return $this->errorHandler;
+    }
+
+    /**
+     * @param Throwable $e
+     * @return void
+     * @throws Throwable
+     */
+    public function error(Throwable $e)
+    {
+        if (!$this->errorHandler) {
+            throw new $e;
+        }
+        ($this->errorHandler)($e);
+    }
 }

+ 9 - 0
src/Worker.php

@@ -1396,6 +1396,9 @@ class Worker
         else
         {
             static::$globalEvent = new Select();
+            static::$globalEvent->setErrorHandler(function ($exception) {
+                static::stopAll(250, $exception);
+            });
             Timer::init(static::$globalEvent);
             foreach($files as $startFile)
             {
@@ -1439,6 +1442,9 @@ class Worker
 
         if (empty(static::$globalEvent)) {
             static::$globalEvent = new Select();
+            static::$globalEvent->setErrorHandler(function ($exception) {
+                static::stopAll(250, $exception);
+            });
             Timer::init(static::$globalEvent);
         }
 
@@ -2367,6 +2373,9 @@ class Worker
         if (!static::$globalEvent) {
             $eventLoopClass = static::getEventLoopName();
             static::$globalEvent = new $eventLoopClass;
+            static::$globalEvent->setErrorHandler(function ($exception) {
+                static::stopAll(250, $exception);
+            });
             $this->resumeAccept();
         }