Skip to content

Commit

Permalink
Don't run loop automatically when explicitly calling stop()
Browse files Browse the repository at this point in the history
  • Loading branch information
clue committed Jun 30, 2021
1 parent f2556b4 commit 4b7727e
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 3 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,25 @@ explicit [`run()`](#run) calls. For BC reasons, the explicit [`run()`](#run)
method is still valid and may still be useful in some applications, especially
for a transition period towards the more concise style.

If you don't want the `Loop` to run automatically, you can either explicitly
[`run()`](#run) or [`stop()`](#stop) it. This can be useful if you're using
a global exception handler like this:

```php
use React\EventLoop\Loop;

Loop::addTimer(10.0, function () {
echo 'Never happens';
});

set_exception_handler(function (Throwable $e) {
echo 'Error: ' . $e->getMessage() . PHP_EOL;
Loop::stop();
});

throw new RuntimeException('Demo');
```

#### get()

The `get(): LoopInterface` method can be used to
Expand Down
11 changes: 8 additions & 3 deletions src/Loop.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ final class Loop
*/
private static $instance;

/** @var bool */
private static $stopped = false;

/**
* Returns the event loop.
* When no loop is set it will it will call the factory to create one.
Expand All @@ -32,22 +35,23 @@ public static function get()

self::$instance = $loop = Factory::create();

// Automatically run loop at end of program, unless already started explicitly.
// Automatically run loop at end of program, unless already started or stopped explicitly.
// This is tested using child processes, so coverage is actually 100%, see BinTest.
// @codeCoverageIgnoreStart
$hasRun = false;
$loop->futureTick(function () use (&$hasRun) {
$hasRun = true;
});

register_shutdown_function(function () use ($loop, &$hasRun) {
$stopped =& self::$stopped;
register_shutdown_function(function () use ($loop, &$hasRun, &$stopped) {
// Don't run if we're coming from a fatal error (uncaught exception).
$error = error_get_last();
if ((isset($error['type']) ? $error['type'] : 0) & (E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR)) {
return;
}

if (!$hasRun) {
if (!$hasRun && !$stopped) {
$loop->run();
}
});
Expand Down Expand Up @@ -215,6 +219,7 @@ public static function run()
*/
public static function stop()
{
self::$stopped = true;
self::get()->stop();
}
}
18 changes: 18 additions & 0 deletions tests/BinTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,22 @@ public function testExecuteExampleWithUndefinedVariableShouldNotRunLoop()

$this->assertLessThan(1.0, $time);
}

public function testExecuteExampleWithExplicitStopShouldNotRunLoop()
{
$time = microtime(true);
exec(escapeshellarg(PHP_BINARY) . ' 21-stop.php 2>/dev/null');
$time = microtime(true) - $time;

$this->assertLessThan(1.0, $time);
}

public function testExecuteExampleWithExplicitStopInExceptionHandlerShouldNotRunLoop()
{
$time = microtime(true);
exec(escapeshellarg(PHP_BINARY) . ' 22-uncaught-stop.php 2>/dev/null');
$time = microtime(true) - $time;

$this->assertLessThan(1.0, $time);
}
}
11 changes: 11 additions & 0 deletions tests/bin/21-stop.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

use React\EventLoop\Loop;

require __DIR__ . '/../../vendor/autoload.php';

Loop::addTimer(10.0, function () {
echo 'never';
});

Loop::stop();
16 changes: 16 additions & 0 deletions tests/bin/22-stop-uncaught.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

use React\EventLoop\Loop;

require __DIR__ . '/../../vendor/autoload.php';

Loop::addTimer(10.0, function () {
echo 'never';
});

set_exception_handler(function (Exception $e) {
echo 'Uncaught error occured' . PHP_EOL;
Loop::stop();
});

throw new RuntimeException();

0 comments on commit 4b7727e

Please sign in to comment.