When AbstractConnection::write() is called after RabbitMQ Server resetting(closing) the TCP connect in some case, PHP buildin function fwrite() (wrapped by AbstractIO::write()) will throw an ErrorException.
/**
* @param string $data
*/
public function write($data)
{
$this->debug->debug_hexdump($data);
try {
$this->io->write($data);
} catch (AMQPConnectionClosedException $e) {
$this->do_close();
throw $e;
} catch (AMQPRuntimeException $e) {
$this->setIsConnected(false);
throw $e;
} catch (\ErrorException $e) {
// Should be caught?
}
}
And there is a piece of code to emulate RabbitMQ Server reset a TCP connection.
<?php
$socket = socket_create_listen(5672);
while ($conn = socket_accept($socket)) {
// If `l_onoff` is non-zero and `l_linger` is zero, all the unsent data will be discarded and RST (reset) is sent to the peer in the case of a connection-oriented socket.
$linger = array ('l_linger' => 0, 'l_onoff' => 1);
socket_set_option ($conn, SOL_SOCKET, SO_LINGER, $linger);
// 8 Bytes Protocol-Header 0-9-1
socket_read($conn, 8);
// 412 Bytes Connection.Start
socket_write($conn,
"\x01\x00\x00\x00\x00\x01\x94\x00\x0a\x00\x0a\x00\x09\x00\x00\x01" .
"\x6f\x0c\x63\x61\x70\x61\x62\x69\x6c\x69\x74\x69\x65\x73\x46\x00" .
"\x00\x00\xa2\x12\x70\x75\x62\x6c\x69\x73\x68\x65\x72\x5f\x63\x6f" .
"\x6e\x66\x69\x72\x6d\x73\x74\x01\x1a\x65\x78\x63\x68\x61\x6e\x67" .
"\x65\x5f\x65\x78\x63\x68\x61\x6e\x67\x65\x5f\x62\x69\x6e\x64\x69" .
"\x6e\x67\x73\x74\x01\x0a\x62\x61\x73\x69\x63\x2e\x6e\x61\x63\x6b" .
"\x74\x01\x16\x63\x6f\x6e\x73\x75\x6d\x65\x72\x5f\x63\x61\x6e\x63" .
"\x65\x6c\x5f\x6e\x6f\x74\x69\x66\x79\x74\x01\x12\x63\x6f\x6e\x6e" .
"\x65\x63\x74\x69\x6f\x6e\x2e\x62\x6c\x6f\x63\x6b\x65\x64\x74\x01" .
"\x13\x63\x6f\x6e\x73\x75\x6d\x65\x72\x5f\x70\x72\x69\x6f\x72\x69" .
"\x74\x69\x65\x73\x74\x01\x1c\x61\x75\x74\x68\x65\x6e\x74\x69\x63" .
"\x61\x74\x69\x6f\x6e\x5f\x66\x61\x69\x6c\x75\x72\x65\x5f\x63\x6c" .
"\x6f\x73\x65\x74\x01\x09\x63\x6f\x70\x79\x72\x69\x67\x68\x74\x53" .
"\x00\x00\x00\x27\x43\x6f\x70\x79\x72\x69\x67\x68\x74\x20\x28\x43" .
"\x29\x20\x32\x30\x30\x37\x2d\x32\x30\x31\x33\x20\x47\x6f\x50\x69" .
"\x76\x6f\x74\x61\x6c\x2c\x20\x49\x6e\x63\x2e\x0b\x69\x6e\x66\x6f" .
"\x72\x6d\x61\x74\x69\x6f\x6e\x53\x00\x00\x00\x35\x4c\x69\x63\x65" .
"\x6e\x73\x65\x64\x20\x75\x6e\x64\x65\x72\x20\x74\x68\x65\x20\x4d" .
"\x50\x4c\x2e\x20\x20\x53\x65\x65\x20\x68\x74\x74\x70\x3a\x2f\x2f" .
"\x77\x77\x77\x2e\x72\x61\x62\x62\x69\x74\x6d\x71\x2e\x63\x6f\x6d" .
"\x2f\x08\x70\x6c\x61\x74\x66\x6f\x72\x6d\x53\x00\x00\x00\x0a\x45" .
"\x72\x6c\x61\x6e\x67\x2f\x4f\x54\x50\x07\x70\x72\x6f\x64\x75\x63" .
"\x74\x53\x00\x00\x00\x08\x52\x61\x62\x62\x69\x74\x4d\x51\x07\x76" .
"\x65\x72\x73\x69\x6f\x6e\x53\x00\x00\x00\x05\x33\x2e\x32\x2e\x34" .
"\x00\x00\x00\x0e\x50\x4c\x41\x49\x4e\x20\x41\x4d\x51\x50\x4c\x41" .
"\x49\x4e\x00\x00\x00\x05\x65\x6e\x5f\x55\x53\xce"
);
// RST Connection
socket_close($conn);
}
fclose($socket);
Both fwrite() and socket_write() are encapsulated in try/catch block. Every ErrorException there gets checked and corresponding meaningfull exception thrown. So it's impossible to get ErrorException from there.
Yes, it is indeed impossible to get ErrorException there. I'm sorry for my carelessness.
While, the error message reported by PHP really confused me, when I missed catching the AMQPConnectionClosedException(socket_strerror($code), $code, $e);, which $e is an ErrorException, PHP told me 'Fatal error: Uncaught exception 'ErrorException' with message 'fwrite(): send of ... and after a long backtrace Next exception 'PhpAmqpLib\Exception\AMQPConnectionClosedException' with message 'Connection reset by peer'' arrived late.
Thanks @huyi1985 , don't stop checking and pointing things up.