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