Subject: | select() and inotify->(poll|read)() |
Date: | Mon, 14 May 2007 16:10:57 +0100 |
To: | bug-Linux-Inotify2 [...] rt.cpan.org |
From: | Alexander Clouter <ac56 [...] soas.ac.uk> |
Hi,
I thought I had discovered a bug however I think its more a 'feature' of the
UNIX select() function that becomes apparent when using it with the fileno of
the inotify object.
I have attached an example perl script that monitors for changes to a file in
the current working directory called 'cheese'. When changed it spits out
output from Data::Dumper on the return array of $inotify->read however when
you press Ctrl-C it should gracefully exit from the core while() loop.
Now originally[1] I found that I needed to press Ctrl-C twice or wait for an
inotify event to occur before it would actually exit. After thinking that
maybe $inotify->read simply pulls out the contents of the event queue rather
than clearing it I slapped in a following $inotify->poll to find that was not
the case.
So, looking deeper into the problem I noticed in the perlfunc manpage for
select() says:
Note: on some Unixes, the select(2) system call may report a socket
file descriptor as "ready for reading", when actually no data is
available, thus a subsequent read blocks. It can be avoided using
always the O_NONBLOCK flag on the socket. See select(2) and fcntl(2)
for further details.
This explains why the select() statement always comes back saying there is
data lurking in the the event queue.
To resolve this problem I set the object to be non-blocking and added an 'if
( @inotifyEvents )' to check there is content lurking in the event queue.
Fortunately due to the workings of select() it does still block until
something does happen to the $reader or event queue so everything works just
nicely.
I have not tested it but I am guessing your Event->io and Glib::IO examples
also 'break' similarly and its worth putting in some documentation to explain
this. If you could mention that[2] after the select()/Event->io/Glib::IO a
check for actual queue content should be done and why that should be so would
be great.
Feel free to include my code as an example, I like to think it gives a good
example, without adding additional perl module dependencies, of how to make
an event based system rather than a timer polled while() loop.
Cheers for an otherwise excellent module.
Alex
[1] before the setting of $inotify to be non-blocking and the 'if (
@inotifyEvents )' check were not present in the original code
[2] if I am right and not similar gotten my code horribly wrong and thus am
wasting your time ;)
Message body is not shown because sender requested not to inline it.