Search code examples
phplibeventreactphp

ReactPHP libevent and socket_pair throws error


I have a problem then I use ReactPHP event-loop with stream_socket_pair.

With StreamSelect loop it works perfectly but then I try to use it with LibEvent extension I got unlimited stream of error:

[warn] kevent: Bad file descriptor

The minimal code to reproduce this error

<?php

require_once __DIR__ . '/vendor/autoload.php';

$loop = React\EventLoop\Factory::create();

$sockets = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);

$pid = pcntl_fork();
if ($pid > 0) {
    fclose($sockets[1]);

    $loop->addReadStream($sockets[0], function ($socket) {
        $data = fread($socket, 100000);
        echo '[' . posix_getpid() . '] Master: ' . $data . PHP_EOL;
    });

    $loop->addTimer(1, function () use ($sockets) {
        fwrite($sockets[0], 'Hello slave!');
    });

    $loop->run();


} else {
    fclose($sockets[0]);

    $loop->addReadStream($sockets[1], function ($socket) {
        $data = fread($socket, 100000);

        echo '[' . posix_getpid() . '] Slave: ' . $data . PHP_EOL;
    });

    $loop->addTimer(1, function () use ($sockets) {
        fwrite($sockets[1], 'Hello master!');
    });

    $loop->run();
    exit();
}

pcntl_wait($status);

Solution

  • It's not related to socket_pair but to process forking. LibEvent states that:

    Some event mechanisms do not survive across fork. The event_base needs to be reinitialized with this function (event_base_reinit).

    After adding "event_base_reinit" after fork everything works then