Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fix a synchronisation bug

The run method will almost always be called inside a thread. This commit fixes
a synchronisation problem between the run and stop methods by explicitly opening
a pipe on the beginning of the run method.

The source of the problem is the fact that when someone stops the watcher,
the @path would become nil and calling the private method pipe would create a new pipe.

A sitiuation where this could be a problem is when the run method is waiting on changes
(blocking on select), note here that @running does not matter anymore, the code is blocking
on select!

Stoping the watcher and firing an event at the same time would unblock the run method
and getting the results in the old code would have created a new pipe and blocked on readline.
  • Loading branch information...
commit fb08ed268339fcf93551a64031008519e9ec6505 1 parent a331537
@Maher4Ever Maher4Ever authored
Showing with 13 additions and 11 deletions.
  1. +13 −11 lib/rb-fsevent/fsevent.rb
View
24 lib/rb-fsevent/fsevent.rb
@@ -32,12 +32,14 @@ def watch(watch_paths, options=nil, &block)
end
def run
+ @pipe = open_pipe
@running = true
+
# please note the use of IO::select() here, as it is used specifically to
# preserve correct signal handling behavior in ruby 1.8.
- while @running && IO::select([pipe], nil, nil, nil)
- if line = pipe.readline
- modified_dir_paths = line.split(":").select { |dir| dir != "\n" }
+ while @running && IO::select([@pipe], nil, nil, nil)
+ if line = @pipe.readline
+ modified_dir_paths = line.split(':').select { |dir| dir != "\n" }
callback.call(modified_dir_paths)
end
end
@@ -47,18 +49,18 @@ def run
end
def stop
- if pipe
- Process.kill("KILL", pipe.pid)
- pipe.close
+ unless @pipe.nil?
+ Process.kill('KILL', @pipe.pid)
+ @pipe.close
end
rescue IOError
ensure
- @pipe = @running = nil
+ @running = false
end
if RUBY_VERSION < '1.9'
- def pipe
- @pipe ||= IO.popen("#{self.class.watcher_path} #{options_string} #{shellescaped_paths}")
+ def open_pipe
+ IO.popen("#{self.class.watcher_path} #{options_string} #{shellescaped_paths}")
end
private
@@ -89,8 +91,8 @@ def shellescape(str)
return str
end
else
- def pipe
- @pipe ||= IO.popen([self.class.watcher_path] + @options + @paths)
+ def open_pipe
+ IO.popen([self.class.watcher_path] + @options + @paths)
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.