amphp / websocket-server

WebSocket component for PHP based on the Amp HTTP server.
MIT License
114 stars 17 forks source link

v3 branch: Cannot switch fibers in destructor when writing to closed websocket #22

Closed bwoebi closed 1 year ago

bwoebi commented 2 years ago
Nov 08 19:38:23 php8.1[534963]: PHP Fatal error:  Uncaught Amp\ByteStream\ClosedException: The stream is not writable in /vendor/amphp/byte-stream/lib/ResourceOutputStream.php:218
Nov 08 19:38:23 php8.1[534963]: Stack trace:
Nov 08 19:38:23 php8.1[534963]: #0 /vendor/amphp/byte-stream/lib/ResourceOutputStream.php(164): Amp\ByteStream\ResourceOutputStream->send('\x81~'!{"memory":[6805852160,6805...', false)
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#1 /vendor/amphp/socket/src/ResourceSocket.php(134): Amp\ByteStream\ResourceOutputStream->write('\x81~'!{"memory":[6805852160,6805...')
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#2 /vendor/amphp/http-server/src/Driver/UpgradedSocket.php(55): Amp\Socket\ResourceSocket->write('\x81~'!{"memory":[6805852160,6805...')
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#3 /vendor/amphp/websocket/src/Rfc6455Client.php(603): Amp\Http\Server\Driver\UpgradedSocket->write('\x81~'!{"memory":[6805852160,6805...')
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#4 /vendor/amphp/websocket/src/Rfc6455Client.php(505): Amp\Websocket\Rfc6455Client->write('{"memory":[6805852160,68058275...', 1, 0, true)
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#5 /vendor/amphp/websocket/src/Rfc6455Client.php(457): Amp\Websocket\Rfc6455Client->sendData('{"memory":[6805852160,68058275...', 1)
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#6 /vendor/amphp/amp/lib/Future.php(137): Amp\Websocket\Rfc6455Client->Amp\Websocket\{closure}(NULL)
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#7 /vendor/revolt/event-loop/src/EventLoop/Internal/AbstractDriver.php(744): Amp\Future::Amp\{closure}(NULL, NULL, 'aeyu')
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#8 [internal function]: Revolt\EventLoop\Internal\AbstractDriver::Revolt\EventLoop\Internal\{closure}()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#9 /vendor/revolt/event-loop/src/EventLoop/Internal/AbstractDriver.php(691): Fiber->resume(Array)
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#10 /vendor/revolt/event-loop/src/EventLoop/Internal/AbstractDriver.php(604): Revolt\EventLoop\Internal\AbstractDriver->invokeMicrotasks()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#11 /vendor/revolt/event-loop/src/EventLoop/Driver/StreamSelectDriver.php(123): Revolt\EventLoop\Internal\AbstractDriver->invokeCallback(Object(Revolt\EventLoop\Internal\TimerCallback))
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#12 /vendor/revolt/event-loop/src/EventLoop/Internal/AbstractDriver.php(676): Revolt\EventLoop\Driver\StreamSelectDriver->dispatch(true)
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#13 /vendor/revolt/event-loop/src/EventLoop/Internal/AbstractDriver.php(96): Revolt\EventLoop\Internal\AbstractDriver->tick()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#14 [internal function]: Revolt\EventLoop\Internal\AbstractDriver->run()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#15 /vendor/revolt/event-loop/src/EventLoop/Suspension.php(95): Fiber->resume()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#16 /vendor/amphp/amp/lib/functions.php(81): Revolt\EventLoop\Suspension->suspend()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#17 /server.php(346): Amp\trapSignal(Array)
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#18 {main}
Nov 08 19:38:23 php8.1[534963]: Next Amp\Websocket\ClosedException: Client unexpectedly closed; Code 1006 (ABNORMAL_CLOSE); Reason: "Writing to the client failed" in /vendor/amphp/websocket/src/Rfc6455Client.php:510
Nov 08 19:38:23 php8.1[534963]: Stack trace:
Nov 08 19:38:23 php8.1[534963]: #0 /vendor/amphp/amp/lib/Future.php(166): Amp\Websocket\Rfc6455Client->Amp\Websocket\{closure}(Object(Amp\ByteStream\ClosedException))
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#1 /vendor/revolt/event-loop/src/EventLoop/Internal/AbstractDriver.php(744): Amp\Future::Amp\{closure}(Object(Amp\ByteStream\ClosedException), NULL, 'aezl')
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#2 [internal function]: Revolt\EventLoop\Internal\AbstractDriver::Revolt\EventLoop\Internal\{closure}()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#3 /vendor/revolt/event-loop/src/EventLoop/Internal/AbstractDriver.php(691): Fiber->resume(Array)
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#4 /vendor/revolt/event-loop/src/EventLoop/Internal/AbstractDriver.php(604): Revolt\EventLoop\Internal\AbstractDriver->invokeMicrotasks()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#5 /vendor/revolt/event-loop/src/EventLoop/Driver/StreamSelectDriver.php(123): Revolt\EventLoop\Internal\AbstractDriver->invokeCallback(Object(Revolt\EventLoop\Internal\TimerCallback))
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#6 /vendor/revolt/event-loop/src/EventLoop/Internal/AbstractDriver.php(676): Revolt\EventLoop\Driver\StreamSelectDriver->dispatch(true)
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#7 /vendor/revolt/event-loop/src/EventLoop/Internal/AbstractDriver.php(96): Revolt\EventLoop\Internal\AbstractDriver->tick()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#8 [internal function]: Revolt\EventLoop\Internal\AbstractDriver->run()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#9 /vendor/revolt/event-loop/src/EventLoop/Suspension.php(95): Fiber->resume()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#10 /vendor/amphp/amp/lib/functions.php(81): Revolt\EventLoop\Suspension->suspend()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#11 /server.php(346): Amp\trapSignal(Array)
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#12 {main}
Nov 08 19:38:23 php8.1[534963]: Next Amp\Future\UnhandledFutureError: Unhandled future error: "Client unexpectedly closed; Code 1006 (ABNORMAL_CLOSE); Reason: "Writing to the client failed""; Await the Future with Future::await() before the future is destroyed or use Future::ignore() to suppress this exception in /vendor/amphp/amp/lib/Internal/FutureState.php:38
Nov 08 19:38:23 php8.1[534963]: Stack trace:
Nov 08 19:38:23 php8.1[534963]: #0 /vendor/revolt/event-loop/src/EventLoop.php(84): Amp\Internal\FutureState->__destruct()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#1 /vendor/amphp/amp/lib/Internal/FutureState.php(135): Revolt\EventLoop::queue(Object(Closure), Object(Amp\Websocket\ClosedException), NULL, 'afar')
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#2 /vendor/amphp/amp/lib/Internal/FutureState.php(111): Amp\Internal\FutureState->invokeCallbacks()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#3 /vendor/amphp/amp/lib/Future.php(168): Amp\Internal\FutureState->error(Object(Amp\Websocket\ClosedException))
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#4 /vendor/revolt/event-loop/src/EventLoop/Internal/AbstractDriver.php(744): Amp\Future::Amp\{closure}(Object(Amp\ByteStream\ClosedException), NULL, 'afaq')
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#5 [internal function]: Revolt\EventLoop\Internal\AbstractDriver::Revolt\EventLoop\Internal\{closure}()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#6 /vendor/revolt/event-loop/src/EventLoop/Internal/AbstractDriver.php(691): Fiber->resume(Array)
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#7 /vendor/revolt/event-loop/src/EventLoop/Internal/AbstractDriver.php(604): Revolt\EventLoop\Internal\AbstractDriver->invokeMicrotasks()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#8 /vendor/revolt/event-loop/src/EventLoop/Driver/StreamSelectDriver.php(123): Revolt\EventLoop\Internal\AbstractDriver->invokeCallback(Object(Revolt\EventLoop\Internal\TimerCallback))
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#9 /vendor/revolt/event-loop/src/EventLoop/Internal/AbstractDriver.php(676): Revolt\EventLoop\Driver\StreamSelectDriver->dispatch(true)
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#10 /vendor/revolt/event-loop/src/EventLoop/Internal/AbstractDriver.php(96): Revolt\EventLoop\Internal\AbstractDriver->tick()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#11 [internal function]: Revolt\EventLoop\Internal\AbstractDriver->run()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#12 /vendor/revolt/event-loop/src/EventLoop/Suspension.php(95): Fiber->resume()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#13 /vendor/amphp/amp/lib/functions.php(81): Revolt\EventLoop\Suspension->suspend()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#14 /server.php(346): Amp\trapSignal(Array)
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#15 {main}
Nov 08 19:38:23 php8.1[534963]:   thrown in /vendor/amphp/amp/lib/Internal/FutureState.php on line 38
Nov 08 19:38:23 php8.1[534963]: PHP Fatal error:  Uncaught FiberError: Cannot switch fibers in current execution context in /vendor/revolt/event-loop/src/EventLoop/Suspension.php:95
Nov 08 19:38:23 php8.1[534963]: Stack trace:
Nov 08 19:38:23 php8.1[534963]: #0 /vendor/revolt/event-loop/src/EventLoop/Suspension.php(95): Fiber->start()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#1 /vendor/amphp/amp/lib/Future.php(236): Revolt\EventLoop\Suspension->suspend()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#2 /vendor/amphp/log/src/StreamHandler.php(34): Amp\Future->await()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#3 /vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php(48): Amp\Log\StreamHandler->write(Array)
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#4 /vendor/monolog/monolog/src/Monolog/Logger.php(327): Monolog\Handler\AbstractProcessingHandler->handle(Array)
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#5 /vendor/monolog/monolog/src/Monolog/Logger.php(513): Monolog\Logger->addRecord(100, 'Close [2001:7e8:f4c4:3801:80f6...', Array)
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#6 /vendor/amphp/http-server/src/Driver/RemoteClient.php(255): Monolog\Logger->debug('Close [2001:7e8:f4c4:3801:80f6...')
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#7 /vendor/amphp/http-server/src/Driver/RemoteClient.php(260): Amp\Http\Server\Driver\RemoteClient->Amp\Http\Server\Driver\{closure}()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#8 /vendor/amphp/http-server/src/Driver/UpgradedSocket.php(45): Amp\Http\Server\Driver\RemoteClient->close()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#9 /vendor/amphp/http-server/src/Driver/UpgradedSocket.php(50): Amp\Http\Server\Driver\UpgradedSocket->close()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#10 [internal function]: Amp\Http\Server\Driver\UpgradedSocket->__destruct()
Nov 08 19:38:23 php8.1[534963]: amphp/http-server#11 {main}
Nov 08 19:38:23 php8.1[534963]:   thrown in /vendor/revolt/event-loop/src/EventLoop/Suspension.php on line 95
trowski commented 2 years ago

Thinking the RemoteClient::onClose() handler needs to be run in microtask.

trowski commented 1 year ago

Fixed this some time ago, on-close callbacks are now executed in an event-loop microtask.