diff --git a/README.md b/README.md index 99db8acc..5f5fc033 100644 --- a/README.md +++ b/README.md @@ -706,6 +706,14 @@ $first = new UnixServer('/tmp/same.sock', $loop); $second = new UnixServer('/tmp/same.sock', $loop); ``` +> Note that these error conditions may vary depending on your system and/or + configuration. + In particular, Zend PHP does only report "Unknown error" when the UDS path + already exists and can not be bound. You may want to check `is_file()` on the + given UDS path to report a more user-friendly error message in this case. + See the exception message and code for more details about the actual error + condition. + Whenever a client connects, it will emit a `connection` event with a connection instance implementing [`ConnectionInterface`](#connectioninterface): diff --git a/src/UnixServer.php b/src/UnixServer.php index 8f1ed983..b7b83608 100644 --- a/src/UnixServer.php +++ b/src/UnixServer.php @@ -61,7 +61,18 @@ public function __construct($path, LoopInterface $loop, array $context = array() stream_context_create(array('socket' => $context)) ); if (false === $this->master) { - throw new RuntimeException('Failed to listen on unix domain socket "' . $path . '": ' . $errstr, $errno); + // PHP does not seem to report errno/errstr for Unix domain sockets (UDS) right now. + // This only applies to UDS server sockets, see also https://3v4l.org/NAhpr. + // Parse PHP warning message containing unknown error, HHVM reports proper info at least. + if ($errno === 0 && $errstr === '') { + $error = error_get_last(); + if (preg_match('/\(([^\)]+)\)|\[(\d+)\]: (.*)/', $error['message'], $match)) { + $errstr = isset($match[3]) ? $match['3'] : $match[1]; + $errno = isset($match[2]) ? (int)$match[2] : 0; + } + } + + throw new RuntimeException('Failed to listen on Unix domain socket "' . $path . '": ' . $errstr, $errno); } stream_set_blocking($this->master, 0); diff --git a/tests/ServerTest.php b/tests/ServerTest.php index 14fdb2c8..29fa177b 100644 --- a/tests/ServerTest.php +++ b/tests/ServerTest.php @@ -50,6 +50,10 @@ public function testConstructorCreatesExpectedTcpServer() public function testConstructorCreatesExpectedUnixServer() { + if (!in_array('unix', stream_get_transports())) { + $this->markTestSkipped('Unix domain sockets (UDS) not supported on your platform (Windows?)'); + } + $loop = Factory::create(); $server = new Server($this->getRandomSocketUri(), $loop); @@ -64,6 +68,28 @@ public function testConstructorCreatesExpectedUnixServer() $server->close(); } + public function testConstructorThrowsForExistingUnixPath() + { + if (!in_array('unix', stream_get_transports())) { + $this->markTestSkipped('Unix domain sockets (UDS) not supported on your platform (Windows?)'); + } + + $loop = Factory::create(); + + try { + $server = new Server('unix://' . __FILE__, $loop); + $this->fail(); + } catch (\RuntimeException $e) { + if ($e->getCode() === 0) { + // Zend PHP does not currently report a sane error + $this->assertStringEndsWith('Unknown error', $e->getMessage()); + } else { + $this->assertEquals(SOCKET_EADDRINUSE, $e->getCode()); + $this->assertStringEndsWith('Address already in use', $e->getMessage()); + } + } + } + public function testEmitsConnectionForNewConnection() { $loop = Factory::create(); diff --git a/tests/UnixServerTest.php b/tests/UnixServerTest.php index 10f7e4f6..70186fa3 100644 --- a/tests/UnixServerTest.php +++ b/tests/UnixServerTest.php @@ -19,6 +19,10 @@ class UnixServerTest extends TestCase */ public function setUp() { + if (!in_array('unix', stream_get_transports())) { + $this->markTestSkipped('Unix domain sockets (UDS) not supported on your platform (Windows?)'); + } + $this->loop = Factory::create(); $this->uds = $this->getRandomSocketUri(); $this->server = new UnixServer($this->uds, $this->loop);