Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

don't throw an exception in an error handler #581

Merged
merged 1 commit into from Oct 8, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
42 changes: 33 additions & 9 deletions PhpAmqpLib/Wire/IO/StreamIO.php
Expand Up @@ -129,7 +129,7 @@ public function connect()
$this->port
);

set_error_handler(array($this, 'error_handler'));
$this->set_error_handler();

try {
$this->sock = stream_socket_client(
Expand All @@ -140,6 +140,7 @@ public function connect()
STREAM_CLIENT_CONNECT,
$this->context
);
$this->cleanup_error_handler();
} catch (\ErrorException $e) {
restore_error_handler();
throw $e;
Expand Down Expand Up @@ -216,14 +217,14 @@ public function read($len)
throw new AMQPRuntimeException('Broken pipe or closed connection');
}

set_error_handler(array($this, 'error_handler'));
$this->set_error_handler();
try {
$buffer = fread($this->sock, ($len - $read));
$this->cleanup_error_handler();
} catch (\ErrorException $e) {
restore_error_handler();
throw $e;
}
restore_error_handler();

if ($buffer === false) {
throw new AMQPRuntimeException('Error receiving data');
Expand Down Expand Up @@ -272,7 +273,7 @@ public function write($data)
throw new AMQPRuntimeException('Broken pipe or closed connection');
}

set_error_handler(array($this, 'error_handler'));
$this->set_error_handler();
// OpenSSL's C library function SSL_write() can balk on buffers > 8192
// bytes in length, so we're limiting the write size here. On both TLS
// and plaintext connections, the write loop will continue until the
Expand All @@ -282,6 +283,7 @@ public function write($data)
// http://comments.gmane.org/gmane.comp.encryption.openssl.user/4361
try {
$buffer = fwrite($this->sock, mb_substr($data, $written, 8192, 'ASCII'), 8192);
$this->cleanup_error_handler();
} catch (\ErrorException $e) {
restore_error_handler();
throw $e;
Expand Down Expand Up @@ -319,8 +321,6 @@ public function write($data)
*/
public function error_handler($errno, $errstr, $errfile, $errline, $errcontext = null)
{
$this->last_error = compact('errno', 'errstr', 'errfile', 'errline', 'errcontext');

// fwrite notice that the stream isn't ready
if (strstr($errstr, 'Resource temporarily unavailable')) {
// it's allowed to retry
Expand All @@ -333,8 +333,31 @@ public function error_handler($errno, $errstr, $errfile, $errline, $errcontext =
return null;
}

// raise all other issues to exceptions
throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
// throwing an exception in an error handler will halt execution
// set the last error and continue
$this->last_error = compact('errno', 'errstr', 'errfile', 'errline', 'errcontext');
}

/**
* Begin tracking errors and set the error handler
*/
protected function set_error_handler()
{
$this->last_error = null;
set_error_handler(array($this, 'error_handler'));
}

/**
* throws an ErrorException if an error was handled
*/
protected function cleanup_error_handler()
{
if ($this->last_error !== null) {
throw new \ErrorException($this->last_error['errstr'], 0, $this->last_error['errno'], $this->last_error['errfile'], $this->last_error['errline']);
}

// no error was caught
restore_error_handler();
}

/**
Expand Down Expand Up @@ -421,9 +444,10 @@ public function select($sec, $usec)
$usec = is_int($usec) ? $usec : 0;
}

set_error_handler(array($this, 'error_handler'));
$this->set_error_handler();
try {
$result = stream_select($read, $write, $except, $sec, $usec);
$this->cleanup_error_handler();
} catch (\ErrorException $e) {
restore_error_handler();
throw $e;
Expand Down