Skip to content

Commit b59f8f1

Browse files
authored
Merge pull request #168 from clue-labs/unix-errors
Improve Unix domain socket (UDS) server error messages
2 parents 476e264 + 9f1d258 commit b59f8f1

File tree

4 files changed

+50
-1
lines changed

4 files changed

+50
-1
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,14 @@ $first = new UnixServer('/tmp/same.sock', $loop);
706706
$second = new UnixServer('/tmp/same.sock', $loop);
707707
```
708708

709+
> Note that these error conditions may vary depending on your system and/or
710+
configuration.
711+
In particular, Zend PHP does only report "Unknown error" when the UDS path
712+
already exists and can not be bound. You may want to check `is_file()` on the
713+
given UDS path to report a more user-friendly error message in this case.
714+
See the exception message and code for more details about the actual error
715+
condition.
716+
709717
Whenever a client connects, it will emit a `connection` event with a connection
710718
instance implementing [`ConnectionInterface`](#connectioninterface):
711719

src/UnixServer.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,18 @@ public function __construct($path, LoopInterface $loop, array $context = array()
6161
stream_context_create(array('socket' => $context))
6262
);
6363
if (false === $this->master) {
64-
throw new RuntimeException('Failed to listen on unix domain socket "' . $path . '": ' . $errstr, $errno);
64+
// PHP does not seem to report errno/errstr for Unix domain sockets (UDS) right now.
65+
// This only applies to UDS server sockets, see also https://3v4l.org/NAhpr.
66+
// Parse PHP warning message containing unknown error, HHVM reports proper info at least.
67+
if ($errno === 0 && $errstr === '') {
68+
$error = error_get_last();
69+
if (preg_match('/\(([^\)]+)\)|\[(\d+)\]: (.*)/', $error['message'], $match)) {
70+
$errstr = isset($match[3]) ? $match['3'] : $match[1];
71+
$errno = isset($match[2]) ? (int)$match[2] : 0;
72+
}
73+
}
74+
75+
throw new RuntimeException('Failed to listen on Unix domain socket "' . $path . '": ' . $errstr, $errno);
6576
}
6677
stream_set_blocking($this->master, 0);
6778

tests/ServerTest.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ public function testConstructorCreatesExpectedTcpServer()
5050

5151
public function testConstructorCreatesExpectedUnixServer()
5252
{
53+
if (!in_array('unix', stream_get_transports())) {
54+
$this->markTestSkipped('Unix domain sockets (UDS) not supported on your platform (Windows?)');
55+
}
56+
5357
$loop = Factory::create();
5458

5559
$server = new Server($this->getRandomSocketUri(), $loop);
@@ -64,6 +68,28 @@ public function testConstructorCreatesExpectedUnixServer()
6468
$server->close();
6569
}
6670

71+
public function testConstructorThrowsForExistingUnixPath()
72+
{
73+
if (!in_array('unix', stream_get_transports())) {
74+
$this->markTestSkipped('Unix domain sockets (UDS) not supported on your platform (Windows?)');
75+
}
76+
77+
$loop = Factory::create();
78+
79+
try {
80+
$server = new Server('unix://' . __FILE__, $loop);
81+
$this->fail();
82+
} catch (\RuntimeException $e) {
83+
if ($e->getCode() === 0) {
84+
// Zend PHP does not currently report a sane error
85+
$this->assertStringEndsWith('Unknown error', $e->getMessage());
86+
} else {
87+
$this->assertEquals(SOCKET_EADDRINUSE, $e->getCode());
88+
$this->assertStringEndsWith('Address already in use', $e->getMessage());
89+
}
90+
}
91+
}
92+
6793
public function testEmitsConnectionForNewConnection()
6894
{
6995
$loop = Factory::create();

tests/UnixServerTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ class UnixServerTest extends TestCase
1919
*/
2020
public function setUp()
2121
{
22+
if (!in_array('unix', stream_get_transports())) {
23+
$this->markTestSkipped('Unix domain sockets (UDS) not supported on your platform (Windows?)');
24+
}
25+
2226
$this->loop = Factory::create();
2327
$this->uds = $this->getRandomSocketUri();
2428
$this->server = new UnixServer($this->uds, $this->loop);

0 commit comments

Comments
 (0)