EvIo and polling backends unable to use php://memory or php://temp

Issue #14 wontfix
Mark K created an issue

On linux, the default backend is EVBACKEND_EPOLL. Both epoll and regular poll cannot handle php:// file streams.

With epoll we get Bad File Descriptor errors

With poll we get Inappropriate ioctl for device errors.

<?php
//works fine with select backend, comment this line to see problem
$defaultLoop =  EvLoop::defaultLoop(Ev::BACKEND_SELECT);

//comment out select and try poll backend
//$defaultLoop =  EvLoop::defaultLoop(Ev::BACKEND_POLL);

//php://memory and php://temp fail with polling backends
$pathToTest = 'php://temp';

//try a regular file
//$pathToTest = '/tmp/foo';

$f = fopen($pathToTest, 'r+');

// Wait until STDIN is readable
$w = new EvIo($f, Ev::READ, function ($watcher, $revents) use ($pathToTest) { 
    echo "$pathToTest is readable\n";
});


//on Linux should dump 4 EPOLL
if (Ev::backend() == Ev::BACKEND_EPOLL || Ev::backend() == Ev::BACKEND_POLL) { 
    echo "using (e)poll backend, warnings about file descriptors...\n";
}

Ev::run(Ev::RUN_ONCE | Ev::RUN_NOWAIT);
usleep(1000);
Ev::run(Ev::RUN_ONCE | Ev::RUN_NOWAIT);
usleep(1000);
Ev::run(Ev::RUN_ONCE | Ev::RUN_NOWAIT);

Comments (8)

  1. Mark K reporter

    This might just need a documentation point about poll backends not working with not real FD.

  2. Ruslan Osmanov repo owner

    The memory based streams have no associated file descriptors, so we can not listen to read/write events there.

    This is how data is written to memory stream: https://github.com/php/php-src/blob/PHP-5.6/main/streams/memory.c#L100 . Just plain memcpy(). Well, the "php://temp" stream wrapper implements a cast to STDIO, but it is done by flushing the data to file, which is not what you probably want: https://github.com/php/php-src/blob/PHP-5.6/main/streams/memory.c#L475

    EvIo::__construct() and EvIo::set() from now on will throw exception in case of memory based stream. Plus warnings replaced with exceptions.

    Actually, the Linux kernel(version 3.17 and above) allows to create a file in RAM with memfd_create() syscall. However, PHP doesn't support this feature yet.

    We might introduce a new stream as well. I don't feel like bloating the ext. with custom streams, though.

    Probably, the simplest solution now is to create a regular file in tmpfs.

  3. Log in to comment