amphp / socket

Non-blocking socket and TLS functionality for PHP based on Amp.
https://amphp.org/socket
MIT License
231 stars 38 forks source link

Unable to read from socket after timeout #85

Closed Mindaho closed 2 years ago

Mindaho commented 2 years ago

Using such code:

$data = yield timeout($socket->read(), 5000)

In case timeout is reached, there is no possibility to read from the socker once again due to ResourceInputStream variable $deferred being defined thus:

 /** @inheritdoc */
    public function read(): Promise
    {
        if ($this->deferred !== null) {
            throw new PendingReadError; // Always exists here
        }
...

Is this intentional, or am I doing something wrong? I have tried calling $socket->unreference() after the timeout, but the use case for that seems completely different.

trowski commented 2 years ago

You can retain a reference to the promise returned from $socket->read() and await that promise again.

$promise = $socket->read();
$data = yield timeout($promise, 5000);

Amp\Promise\timeout() returns a new promise that fails after the given time, but $promise is still pending and can be awaited with a timeout again.


We realize this is not necessarily intuitive, and this API has changed in the Amp v3 compatible version of this library to use Cancellation.

$data = $socket->read(new TimeoutCancellation(5));
// If CancelledException is thrown, $socket->read() may be called again
Mindaho commented 2 years ago

Thanks for the response. Not the prettiest solution for now, but it works. Had to also update the read promise after successful read or else same data will be returned over and over again (logical but got me for a second, so writing it here in case someone get stuck on same situation).