Xrefresh server, rb-inotify and ioselect

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 W.

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

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 W.

On Thu, Jan 14, 2010 at 8:36 AM, Marc W. [email protected] wrote:

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.

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

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs