Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into HEAD
Browse files Browse the repository at this point in the history
  • Loading branch information
danog committed May 1, 2024
2 parents f2f634f + 358572c commit 7cc40ca
Show file tree
Hide file tree
Showing 19 changed files with 323 additions and 121 deletions.
21 changes: 17 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,20 @@ jobs:
matrix:
include:
- operating-system: 'ubuntu-latest'
php-version: '8.1'
composer-flags: '--ignore-platform-req=php'
php-version: 8.1
composer-flags: '--ignore-platform-req=php+'
- operating-system: 'ubuntu-latest'
php-version: 8.2
composer-flags: '--ignore-platform-req=php+'
- operating-system: 'ubuntu-latest'
php-version: 8.3
composer-flags: '--ignore-platform-req=php+'
- operating-system: 'ubuntu-latest'
php-version: 8.4
composer-flags: '--ignore-platform-req=php+'
psalm: none

name: PHP ${{ matrix.php-version }} ${{ matrix.job-description }}

runs-on: ${{ matrix.operating-system }}

steps:
Expand Down Expand Up @@ -66,10 +75,14 @@ jobs:
composer info -D
- name: Run tests
run: vendor/bin/phpunit ${{ matrix.phpunit-flags }}
run: php vendor/bin/phpunit

- name: Run tests without pcntl
run: php -d disable_functions=pcntl_signal_dispatch vendor/bin/phpunit

- name: Run Psalm
run: vendor/bin/psalm.phar --show-info=true
if: matrix.psalm != 'none'

- name: Run style fixer
env:
Expand Down
2 changes: 1 addition & 1 deletion .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public function getRules(): array
"allow_single_line_closure" => true,
],
"array_syntax" => ["syntax" => "short"],
"blank_lines_before_namespace" => true,
"cast_spaces" => true,
"combine_consecutive_unsets" => true,
"declare_strict_types" => true,
Expand Down Expand Up @@ -73,7 +74,6 @@ public function getRules(): array
"psr_autoloading" => ['dir' => $this->src],
"return_type_declaration" => ["space_before" => "none"],
"short_scalar_cast" => true,
"single_blank_line_before_namespace" => true,
"line_ending" => true,
];
}
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

The MIT License (MIT)

Copyright (c) 2021-2022 Revolt (Aaron Piotrowski, Cees-Jan Kiewiet, Christian Lück, Niklas Keller, and contributors)
Copyright (c) 2021-2023 Revolt (Aaron Piotrowski, Cees-Jan Kiewiet, Christian Lück, Niklas Keller, and contributors)
Copyright (c) 2015-2021 amphp (Daniel Lowrey, Aaron Piotrowski, Niklas Keller, Bob Weinand, and contributors)
Copyright (c) 2012-2021 ReactPHP (Christian Lück, Cees-Jan Kiewiet, Jan Sorgalla, Chris Boden, Igor Wiedler, and contributors)
Copyright (c) 2016 PHP Asynchronous Interoperability Group
Expand Down
12 changes: 12 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Security Policy

## Supported Versions

| Version | Supported |
| ------- | ------------------ |
| 1.x | ✔️ |
| < 1.x | :x: |

## Reporting a Vulnerability

If you think you've found a vulnerability, please use the [private vulnerability reporting form provided by Github](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability).
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"ext-json": "*",
"phpunit/phpunit": "^9",
"jetbrains/phpstorm-stubs": "^2019.3",
"psalm/phar": "^4.7"
"psalm/phar": "^5.15"
},
"autoload": {
"psr-4": {
Expand Down
2 changes: 1 addition & 1 deletion examples/generate-yes.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
$r = \fwrite($stdout, $data);

// nothing could be written despite being writable => closed
if ($r === 0) {
if ($r === 0 || $r === false) {
EventLoop::cancel($watcher);
\stream_set_blocking($stdout, true);
\fclose($stdout);
Expand Down
13 changes: 13 additions & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,19 @@
<file name="src/EventLoop/Driver/UvDriver.php"/>
</errorLevel>
</PossiblyInvalidArgument>

<UnsupportedPropertyReferenceUsage>
<errorLevel type="suppress">
<directory name="src"/>
</errorLevel>
</UnsupportedPropertyReferenceUsage>

<PossiblyInvalidArgument>
<errorLevel type="suppress">
<directory name="examples" />
<file name="src/EventLoop/Driver/UvDriver.php" />
</errorLevel>
</PossiblyInvalidArgument>
</issueHandlers>

<stubs>
Expand Down
4 changes: 2 additions & 2 deletions src/EventLoop.php
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ public static function getType(string $callbackId): CallbackType
*
* @param string $callbackId The callback identifier.
*
* @return bool {@code true} if the callback is currently enabled, otherwise {@code false}.
* @return bool `true` if the callback is currently enabled, otherwise `false`.
*/
public static function isEnabled(string $callbackId): bool
{
Expand All @@ -358,7 +358,7 @@ public static function isEnabled(string $callbackId): bool
*
* @param string $callbackId The callback identifier.
*
* @return bool {@code true} if the callback is currently referenced, otherwise {@code false}.
* @return bool `true` if the callback is currently referenced, otherwise `false`.
*/
public static function isReferenced(string $callbackId): bool
{
Expand Down
6 changes: 3 additions & 3 deletions src/EventLoop/Driver.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ interface Driver
* exception is thrown that cannot be handled. Exceptions that cannot be handled are exceptions thrown from an
* error handler or exceptions that would be passed to an error handler but none exists to handle them.
*
* @throw \Error Thrown if the event loop is already running.
* @throws \Error Thrown if the event loop is already running.
*/
public function run(): void;

Expand Down Expand Up @@ -294,7 +294,7 @@ public function getType(string $callbackId): CallbackType;
*
* @param string $callbackId The callback identifier.
*
* @return bool {@code true} if the callback is currently enabled, otherwise {@code false}.
* @return bool `true` if the callback is currently enabled, otherwise `false`.
*/
public function isEnabled(string $callbackId): bool;

Expand All @@ -303,7 +303,7 @@ public function isEnabled(string $callbackId): bool;
*
* @param string $callbackId The callback identifier.
*
* @return bool {@code true} if the callback is currently referenced, otherwise {@code false}.
* @return bool `true` if the callback is currently referenced, otherwise `false`.
*/
public function isReferenced(string $callbackId): bool;

Expand Down
8 changes: 5 additions & 3 deletions src/EventLoop/Driver/StreamSelectDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ public function __construct(?FiberFactory $fiberFactory = null)

$this->signalQueue = new \SplQueue();
$this->timerQueue = new TimerQueue();
$this->signalHandling = \extension_loaded("pcntl");
$this->signalHandling = \extension_loaded("pcntl")
&& \function_exists('pcntl_signal_dispatch')
&& \function_exists('pcntl_signal');

$this->streamSelectErrorHandler = function (int $errno, string $message): void {
// Casing changed in PHP 8 from 'unable' to 'Unable'
Expand Down Expand Up @@ -276,7 +278,7 @@ private function selectStreams(array $read, array $write, float $timeout): void
}

/** @var array<int, resource>|null $except */
if ($except) {
if ($except !== null) {
foreach ($except as $key => $socket) {
$write[$key] = $socket;
}
Expand All @@ -303,7 +305,7 @@ private function selectStreams(array $read, array $write, float $timeout): void
}

if ($timeout > 0) { // Sleep until next timer expires.
/** @psalm-var positive-int $timeout */
/** @psalm-suppress ArgumentTypeCoercion $timeout is positive here. */
\usleep((int) ($timeout * 1_000_000));
}
}
Expand Down
13 changes: 10 additions & 3 deletions src/EventLoop/Driver/TracingDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,15 @@ private function getCancelTrace(string $callbackId): string
/**
* Formats a stacktrace obtained via `debug_backtrace()`.
*
* @param array<array{file?: string, line: int, type?: string, class?: class-string, function: string}> $trace
* Output of `debug_backtrace()`.
* @param list<array{
* args?: list<mixed>,
* class?: class-string,
* file?: string,
* function: string,
* line?: int,
* object?: object,
* type?: string
* }> $trace Output of `debug_backtrace()`.
*
* @return string Formatted stacktrace.
*/
Expand All @@ -259,7 +266,7 @@ private function formatStacktrace(array $trace): string
return \implode("\n", \array_map(static function ($e, $i) {
$line = "#{$i} ";

if (isset($e["file"])) {
if (isset($e["file"], $e['line'])) {
$line .= "{$e['file']}:{$e['line']} ";
}

Expand Down
32 changes: 16 additions & 16 deletions src/EventLoop/Driver/UvDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public static function isSupported(): bool
/** @var array<string, resource> */
private array $events = [];
/** @var array<int, array<array-key, DriverCallback>> */
private array $callbacks = [];
private array $uvCallbacks = [];
/** @var array<int, resource> */
private array $streams = [];
private readonly \Closure $ioCallback;
Expand All @@ -39,7 +39,7 @@ public function __construct(?FiberFactory $fiberFactory = null)
$this->handle = \uv_loop_new();

$this->ioCallback = function ($event, $status, $events, $resource): void {
$callbacks = $this->callbacks[(int) $event];
$callbacks = $this->uvCallbacks[(int) $event];

// Invoke the callback on errors, as this matches behavior with other loop back-ends.
// Re-enable callback as libuv disables the callback on non-zero status.
Expand Down Expand Up @@ -67,15 +67,15 @@ public function __construct(?FiberFactory $fiberFactory = null)
};

$this->timerCallback = function ($event): void {
$callback = $this->callbacks[(int) $event][0];
$callback = $this->uvCallbacks[(int) $event][0];

\assert($callback instanceof TimerCallback);

$this->enqueueCallback($callback);
};

$this->signalCallback = function ($event): void {
$callback = $this->callbacks[(int) $event][0];
$callback = $this->uvCallbacks[(int) $event][0];

$this->enqueueCallback($callback);
};
Expand All @@ -95,16 +95,16 @@ public function cancel(string $callbackId): void
$event = $this->events[$callbackId];
$eventId = (int) $event;

if (isset($this->callbacks[$eventId][0])) { // All except IO callbacks.
unset($this->callbacks[$eventId]);
} elseif (isset($this->callbacks[$eventId][$callbackId])) {
$callback = $this->callbacks[$eventId][$callbackId];
unset($this->callbacks[$eventId][$callbackId]);
if (isset($this->uvCallbacks[$eventId][0])) { // All except IO callbacks.
unset($this->uvCallbacks[$eventId]);
} elseif (isset($this->uvCallbacks[$eventId][$callbackId])) {
$callback = $this->uvCallbacks[$eventId][$callbackId];
unset($this->uvCallbacks[$eventId][$callbackId]);

\assert($callback instanceof StreamCallback);

if (empty($this->callbacks[$eventId])) {
unset($this->callbacks[$eventId], $this->streams[(int) $callback->stream]);
if (empty($this->uvCallbacks[$eventId])) {
unset($this->uvCallbacks[$eventId], $this->streams[(int) $callback->stream]);
}
}

Expand Down Expand Up @@ -162,10 +162,10 @@ protected function activate(array $callbacks): void

$eventId = (int) $event;
$this->events[$id] = $event;
$this->callbacks[$eventId][$id] = $callback;
$this->uvCallbacks[$eventId][$id] = $callback;

$flags = 0;
foreach ($this->callbacks[$eventId] as $w) {
foreach ($this->uvCallbacks[$eventId] as $w) {
\assert($w instanceof StreamCallback);

$flags |= $w->enabled ? ($this->getStreamCallbackFlags($w)) : 0;
Expand All @@ -178,7 +178,7 @@ protected function activate(array $callbacks): void
$event = $this->events[$id] = \uv_timer_init($this->handle);
}

$this->callbacks[(int) $event] = [$callback];
$this->uvCallbacks[(int) $event] = [$callback];

\uv_timer_start(
$event,
Expand All @@ -194,7 +194,7 @@ protected function activate(array $callbacks): void
$event = $this->events[$id] = \uv_signal_init($this->handle);
}

$this->callbacks[(int) $event] = [$callback];
$this->uvCallbacks[(int) $event] = [$callback];

/** @psalm-suppress TooManyArguments */
\uv_signal_start($event, $this->signalCallback, $callback->signal);
Expand Down Expand Up @@ -225,7 +225,7 @@ protected function deactivate(DriverCallback $callback): void

if ($callback instanceof StreamCallback) {
$flags = 0;
foreach ($this->callbacks[(int) $event] as $w) {
foreach ($this->uvCallbacks[(int) $event] as $w) {
\assert($w instanceof StreamCallback);

$flags |= $w->invokable ? ($this->getStreamCallbackFlags($w)) : 0;
Expand Down
2 changes: 2 additions & 0 deletions src/EventLoop/DriverFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public function create(): Driver
return new StreamSelectDriver();
})();

/** @psalm-suppress RiskyTruthyFalsyComparison */
if (\getenv("REVOLT_DRIVER_DEBUG_TRACE")) {
return new TracingDriver($driver);
}
Expand All @@ -56,6 +57,7 @@ private function createDriverFromEnv(): ?Driver
{
$driver = \getenv("REVOLT_DRIVER");

/** @psalm-suppress RiskyTruthyFalsyComparison */
if (!$driver) {
return null;
}
Expand Down
Loading

0 comments on commit 7cc40ca

Please sign in to comment.