SSH2: attempt at fixing stream_select(): unable to select [4]

This commit is contained in:
terrafrost 2023-05-10 03:46:37 -05:00
parent 3334a3243c
commit 5a7569cd13

View File

@ -1280,6 +1280,32 @@ class SSH2
$this->send_kex_first = false;
}
/**
* stream_select wrapper
*
* Quoting https://stackoverflow.com/a/14262151/569976,
* "The general approach to `EINTR` is to simply handle the error and retry the operation again"
*
* This wrapper does that loop
*/
private static function stream_select(&$read, &$write, &$except, $seconds, $microseconds = null)
{
$remaining = $seconds + $microseconds / 1000000;
$start = microtime(true);
while (true) {
$result = @stream_select($read, $write, $except, $seconds, $microseconds);
if ($result !== false) {
return $result;
}
$elapsed = microtime(true) - $start;
$seconds = (int) ($remaining - floor($elapsed));
$microseconds = (int) (1000000 * ($remaining - $seconds));
if ($elapsed >= $remaining) {
return false;
}
}
}
/**
* Connect to an SSHv2 server
*
@ -1344,7 +1370,7 @@ class SSH2
$start = microtime(true);
$sec = (int) floor($this->curTimeout);
$usec = (int) (1000000 * ($this->curTimeout - $sec));
if (@stream_select($read, $write, $except, $sec, $usec) === false) {
if (static::stream_select($read, $write, $except, $sec, $usec) === false) {
throw new \RuntimeException('Connection timed out whilst receiving server identification string');
}
$elapsed = microtime(true) - $start;
@ -3399,9 +3425,9 @@ class SSH2
if (!$this->curTimeout) {
if ($this->keepAlive <= 0) {
@stream_select($read, $write, $except, null);
static::stream_select($read, $write, $except, null);
} else {
if (!@stream_select($read, $write, $except, $this->keepAlive)) {
if (!static::stream_select($read, $write, $except, $this->keepAlive)) {
$this->send_binary_packet(pack('CN', NET_SSH2_MSG_IGNORE, 0));
return $this->get_binary_packet(true);
}
@ -3415,7 +3441,7 @@ class SSH2
$start = microtime(true);
if ($this->keepAlive > 0 && $this->keepAlive < $this->curTimeout) {
if (!@stream_select($read, $write, $except, $this->keepAlive)) {
if (!static::stream_select($read, $write, $except, $this->keepAlive)) {
$this->send_binary_packet(pack('CN', NET_SSH2_MSG_IGNORE, 0));
$elapsed = microtime(true) - $start;
$this->curTimeout -= $elapsed;
@ -3429,7 +3455,7 @@ class SSH2
$usec = (int) (1000000 * ($this->curTimeout - $sec));
// this can return a "stream_select(): unable to select [4]: Interrupted system call" error
if (!@stream_select($read, $write, $except, $sec, $usec)) {
if (!static::stream_select($read, $write, $except, $sec, $usec)) {
$this->is_timeout = true;
return true;
}