diff --git a/src/EventLoop.php b/src/EventLoop.php index 1b81136..c087892 100644 --- a/src/EventLoop.php +++ b/src/EventLoop.php @@ -20,7 +20,7 @@ */ final class EventLoop { - private static Driver $driver; + private static ?Driver $driver = null; /** * Sets the driver to be used as the event loop. @@ -55,6 +55,11 @@ public function getHandle(): mixed return null; } + public function __destruct() + { + // do nothing + } + protected function now(): float { return (float) \hrtime(true) / 1_000_000_000; diff --git a/src/EventLoop/Driver/EvDriver.php b/src/EventLoop/Driver/EvDriver.php index e0a33a3..b5ed199 100644 --- a/src/EventLoop/Driver/EvDriver.php +++ b/src/EventLoop/Driver/EvDriver.php @@ -91,6 +91,8 @@ public function __destruct() // We need to clear all references to events manually, see // https://bitbucket.org/osmanov/pecl-ev/issues/31/segfault-in-ev_timer_stop $this->events = []; + + parent::__destruct(); } /** diff --git a/src/EventLoop/Driver/EventDriver.php b/src/EventLoop/Driver/EventDriver.php index 869c3a9..a3ac5e6 100644 --- a/src/EventLoop/Driver/EventDriver.php +++ b/src/EventLoop/Driver/EventDriver.php @@ -93,6 +93,8 @@ public function __destruct() $this->handle->free(); unset($this->handle); } + + parent::__destruct(); } /** diff --git a/src/EventLoop/Driver/StreamSelectDriver.php b/src/EventLoop/Driver/StreamSelectDriver.php index 4f1b78f..5028f0b 100644 --- a/src/EventLoop/Driver/StreamSelectDriver.php +++ b/src/EventLoop/Driver/StreamSelectDriver.php @@ -87,6 +87,8 @@ public function __destruct() $this->deactivate($signalCallback); } } + + parent::__destruct(); } /** diff --git a/src/EventLoop/Internal/AbstractDriver.php b/src/EventLoop/Internal/AbstractDriver.php index 94de316..747e1f7 100644 --- a/src/EventLoop/Internal/AbstractDriver.php +++ b/src/EventLoop/Internal/AbstractDriver.php @@ -4,6 +4,8 @@ namespace Revolt\EventLoop\Internal; +use ReflectionProperty; +use Revolt\EventLoop; use Revolt\EventLoop\CallbackType; use Revolt\EventLoop\Driver; use Revolt\EventLoop\FiberLocal; @@ -103,6 +105,16 @@ public function __construct() }; } + public function __destruct() + { + // Unset event loop singleton to avoid reusing a dead event loop instance during garbage collection. + // Using reflection to avoid exposing public (even @internal methods). + $refl = new ReflectionProperty(EventLoop::class, 'driver'); + if ($refl->getValue() === $this) { + $refl->setValue(null, null); + } + } + public function run(): void { if ($this->fiber->isRunning()) {