Is it OK to poll() a device file descriptor

Is it OK to poll() a device file descriptor

Elazar Leibovich elazarl at gmail.com
Tue Jun 18 22:16:45 IDT 2013


I'm using it as a fake "always non-blocking" file descriptor.

My main libevent-like poll loop looks like:

    poll(fds)
    for fd in fds:
       if fd.revents | POLLIN:
           fd.read_callback()
       if fd.revents | POLLOUT:
           fd.write_callback()

Now let's say I want a fake filedescriptor that always reads 'z's (a sleepy
fd).
A simple way to implement that is to have a callback function associated
with "/dev/zero" (so that poll will always say it's available to read
from), and in the write callback we'll simply ignore the filedescriptor and
write 'z's to the given buffer.

Something like:

    register_with_poll(devzero, write_z_cb);

    int write_z_cb(int fd, char *buf, int len) {
        memset(buf, 'z', len);
        return len;
    }

I can still do that with non-blocking pipe I'll never write to (and since
its buffer is empty it'll never block), but somehow I found /dev/zero to be
more elegant.


On Tue, Jun 18, 2013 at 8:42 PM, Shachar Shemesh <shachar at shemesh.biz>wrote:

>  On 18/06/13 17:43, Elazar Leibovich wrote:
>
>  Try to open /dev/null, and then to poll the file descriptor. Neither in
> the man page nor in the standard I see anything preventing you to poll on
> /dev/null, yet, it does not work on Mac OS X. You get a POLLNVAL.
>
>   Under Linux, whether you can poll (epoll, select) a character device
> depends on the device's implementation. If the device implements it, then
> you can. If not, you can't.
>
> Under Linux, the device driver's implementer implements one callback, and
> the kernel uses that to allow select, poll and epoll (plus the "p" variants
> of the above) all at once. On Mac OS X, however, the BUGS line Oleg pointed
> to does not appear in the select syscall interface, which means that it
> might be possible to select a device file descriptor.
>
> Our of curiosity, however, why would you want to poll /dev/null?
>
> Shachar
>
> Run the following:
>
>  https://gist.github.com/elazarl/5805848
>
>  #include <stdio.h>
> #include <poll.h>
>
> #include <fcntl.h>
>
>
> int main() {
>     int fd = open("/dev/null", O_WRONLY);
>     struct pollfd pollfds = { fd, POLLOUT, 0 };
>     if (fd < 0) {
>         perror("open");
>         return 1;
>
>     }
>     if (poll(&pollfds, 1, -1) < 0) {
>         perror("poll");
>         return 2;
>
>     }
>     if (pollfds.revents == POLLNVAL) {
>         puts("huh? why poll({/dev/null, POLLOUT, 0}, 1) returns POLLNVAL?");
>     }
>     if (pollfds.revents == POLLOUT) {
>         puts("working as expected");
>     }
>     return 0;
> }
> Is there anything I'm missing? Or is it a real vaguely implemented corner of the standard.
> If it is, I'll be glad to see a list of supported/unsupported platforms,
> as well as list of other corner cases (for instance, POLLHUP may or may be received on EOF).
>
>
>
> _______________________________________________
> Linux-il mailing listLinux-il at cs.huji.ac.ilhttp://mailman.cs.huji.ac.il/mailman/listinfo/linux-il
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.cs.huji.ac.il/pipermail/linux-il/attachments/20130618/affb195b/attachment.html>


More information about the Linux-il mailing list