From 4058fe910a6a621f2e1071dde06df4c9b6c8aa3a Mon Sep 17 00:00:00 2001 From: Aman Gupta Date: Mon, 16 Mar 2009 19:41:54 -0700 Subject: [PATCH] Inotify fixes: file_delete only fires after fds have been closed, use syscall hackery for older linux distributions (*cough* debian) --- ext/em.cpp | 2 +- ext/extconf.rb | 3 ++- ext/project.h | 21 +++++++++++++++++---- lib/em/filewatcher.rb | 3 +++ tests/test_file_watch.rb | 2 +- 5 files changed, 24 insertions(+), 7 deletions(-) diff --git a/ext/em.cpp b/ext/em.cpp index a27898226..324fe2d57 100644 --- a/ext/em.cpp +++ b/ext/em.cpp @@ -2054,7 +2054,7 @@ void EventMachine_t::_ReadInotifyEvents() msg = ""; if (EventCallback && strlen(msg) > 0) - (*EventCallback)(Watches [event->wd]->GetBinding().c_str(), EM_CONNECTION_READ, msg, strlen(msg)); + (*EventCallback)(Watches [event.wd]->GetBinding().c_str(), EM_CONNECTION_READ, msg, strlen(msg)); } #endif } diff --git a/ext/extconf.rb b/ext/extconf.rb index b72f3b21e..3f94f6f95 100644 --- a/ext/extconf.rb +++ b/ext/extconf.rb @@ -15,7 +15,8 @@ def add_define(name) add_define 'BUILD_FOR_RUBY' add_define 'HAVE_RBTRAP' if have_var('rb_trap_immediate', ['ruby.h', 'rubysig.h']) add_define "HAVE_TBR" if have_func('rb_thread_blocking_region')# and have_macro('RUBY_UBF_IO', 'ruby.h') -add_define "HAVE_INOTIFY" if have_func('inotify_init', ['sys/inotify.h']) +add_define "HAVE_INOTIFY" if inotify = have_func('inotify_init', 'sys/inotify.h') +add_define "HAVE_OLD_INOTIFY" if !inotify && have_macro('__NR_inotify_init', 'sys/syscall.h') # Minor platform details between *nix and Windows: diff --git a/ext/project.h b/ext/project.h index 890d6c8bf..eff510591 100644 --- a/ext/project.h +++ b/ext/project.h @@ -55,10 +55,6 @@ See the file COPYING for complete licensing information. #include #include #include -#ifdef HAVE_INOTIFY -#include -#define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event)) -#endif typedef int SOCKET; #define closesocket close #define INVALID_SOCKET -1 @@ -106,6 +102,23 @@ using namespace std; #include #endif +#ifdef HAVE_INOTIFY +#include +#endif + +#ifdef HAVE_OLD_INOTIFY +#include +#include +static inline int inotify_init (void) { return syscall (__NR_inotify_init); } +static inline int inotify_add_watch (int fd, const char *name, __u32 mask) { return syscall (__NR_inotify_add_watch, fd, name, mask); } +static inline int inotify_rm_watch (int fd, __u32 wd) { return syscall (__NR_inotify_rm_watch, fd, wd); } +#define HAVE_INOTIFY 1 +#endif + +#ifdef HAVE_INOTIFY +#define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event)) +#endif + #include "binder.h" #include "em.h" #include "epoll.h" diff --git a/lib/em/filewatcher.rb b/lib/em/filewatcher.rb index eb2b89823..e9299c275 100644 --- a/lib/em/filewatcher.rb +++ b/lib/em/filewatcher.rb @@ -29,6 +29,9 @@ def file_modified # Should be redefined with the user's custom callback that will be fired when the file is deleted. # When the file is deleted, stop_watching will be called after this to make sure everything is # cleaned up correctly. + # + # Note that on linux (with inotify), file_deleted will not be called until all open file descriptors to + # the file have been closed. def file_deleted end diff --git a/tests/test_file_watch.rb b/tests/test_file_watch.rb index 26c10411c..f0087d116 100644 --- a/tests/test_file_watch.rb +++ b/tests/test_file_watch.rb @@ -38,7 +38,7 @@ def test_events File.open(file.path, 'w'){ |f| f.puts 'hi' } # delete it - EM.add_timer(0.25){ file.delete } + EM.add_timer(0.25){ file.close; file.delete } } assert_equal($path, $tmp_path)