xrefresh server, rb-inotify and ioselect

M

Marc Weber

Hi,

This is of interest for all Linux devs doing web development.

I patched the xrefresh server so that it runs on Linux. Not everything
is implemented but it is useable: http://github.com/MarcWeber/xrefresh-server
Changes will be merged upstream soon.

The question I have is about IO.select line 97
http://github.com/MarcWeber/xrefresh-server/blob/linux/lib/xrefresh-server/linux/monitor.rb

I think when running this app a long time I get bad file descriptor.
When using a wait time of 0.01 I get this error message very soon.

Is this a known issue? I contacted the author of rb-inotify. He told me
I should rewrite the io select loop using C and see whether the same
problem occurs. However you may just know about this issue without me
rewriting everything in C.. In fact it doesn't hurt me much. I'm
just curious.

So is there someone who wants to try xrefresh on Linux and can verify
this behaviour?

Note:
You have to list each file you want to watch in the config path section.

Marc Weber

PS: I am new to ruby so I may have done something obviously stupid.
 
M

Marc Weber

I've tracked it down:

This example

require 'rb-inotify'
notifier = INotify::Notifier.new

begin
io = notifier.to_io
nr = 1
while true
nr = nr +1
if IO.select([notifier.to_io], [], [], 0.0001) # 0.01 yields "bad file descriptor!
notifier.process
end
end

rescue
puts "nr is #{nr}"
end

outputs:

tmp i%for i in `seq 20`; do ruby test.rb; done /tmp nixos
nr is 6768
nr is 6768
nr is 6770
nr is 6768
nr is 6770
nr is 6768
nr is 6768
nr is 6770
nr is 6768
nr is 6768
nr is 6768
nr is 6768
nr is 6768
nr is 6769
nr is 6768
nr is 6769
nr is 6768
nr is 6768
nr is 6770
nr is 6769


So the problem occurs roughly after the same amount of to_io calls.
using lsof -p $THIS_RUBY_PROCESS it shows the file descriptor is gone!

When suspending the prog while there is no error looking at losf -p $PID
output shows that file descriptor 3 is connected to inotify.
So it must be notifier.to_io which is causing trouble. I added a puts to
verify that the file descriptor is always 3.

So my fix is easy: use notifier.to_io to define a local var and use
that local var within the IO.select loop. Then my problem is gone

Nathan: Can you recommend this example instead?

io = notifier.to_io
while true
if IO.select([io], [], [], 0.0001)
notifier.process
end
end

This seems to work. I'm still interested what's causing this trouble.
Obviously there is a problem with the to_io code which looks like this:


def to_io
raise NotImplementedError.new("INotify::Notifier#to_io is not supported under JRuby") if RUBY_PLATFORM =~ /java/
IO.new(@fd)
end

So ruby doesn't like callign IO.new(@fd) over and over again.

Is this a bug?

Marc Weber
 
C

Charles Oliver Nutter

This seems to work. I'm still interested what's causing this trouble.
Obviously there is a problem with the to_io code which looks like this:


=C2=A0def to_io
=C2=A0 =C2=A0raise NotImplementedError.new("INotify::Notifier#to_io is no=
t supported under JRuby") if RUBY_PLATFORM =3D~ /java/
=C2=A0 =C2=A0IO.new(@fd)
=C2=A0end

So ruby doesn't like callign IO.new(@fd) over and over again.

If you create an IO object to wrap an fd, when it GCs it will close
that fd. I'm not sure if there's a way to "detach" from a given fd so
it doesn't close. You might prefer reopen instead of creating new IOs
every time.

- Charlie
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,817
Latest member
DicWeils

Latest Threads

Top