diff --git a/src/Factory.php b/src/Factory.php index 79406bb..a861e6b 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -128,6 +128,10 @@ public function createReceiver($address) throw new RuntimeException('Unable to enable SO_REUSEADDR'); } + set_error_handler(function () { + // ignore PHP warning, error is reported via socket_last_error() below + }); + // join multicast group and bind to port $ret = socket_set_option( $socket, @@ -135,8 +139,12 @@ public function createReceiver($address) MCAST_JOIN_GROUP, array('group' => $parts['host'], 'interface' => 0) ); + + restore_error_handler(); + if ($ret === false) { - throw new RuntimeException('Unable to join multicast group'); + $errno = socket_last_error($socket); + throw new RuntimeException('Unable to join multicast group: ' . socket_strerror($errno), $errno); } return new DatagramSocket($this->loop, $stream); diff --git a/tests/FunctionalTest.php b/tests/FunctionalTest.php index 9d92850..59e446c 100644 --- a/tests/FunctionalTest.php +++ b/tests/FunctionalTest.php @@ -58,6 +58,31 @@ public function testMultipleReceivers() $this->loop->run(); } + public function testCreateReceiverThrowsForNonMulticastAddressWithoutCallingCustomErrorHandler() + { + if (!defined('MCAST_JOIN_GROUP') || !function_exists('socket_import_stream')) { + $this->markTestSkipped('No multicast support'); + } + + $error = null; + set_error_handler(function ($_, $errstr) use (&$error) { + $error = $errstr; + }); + + $this->setExpectedException('RuntimeException', 'Unable to join multicast group: ' . socket_strerror(SOCKET_EINVAL), SOCKET_EINVAL); + + try { + $this->factory->createReceiver('127.0.0.1:2244'); + + restore_error_handler(); + } catch (\Exception $e) { + restore_error_handler(); + $this->assertNull($error); + + throw $e; + } + } + public function testConstructWithoutLoopAssignsLoopAutomatically() { $factory = new Factory();