Browse Source

Partially revert back changes in the FileWatcher class.
The thread needs to be stopped before closing the file watcher on OSX platform to avoid segfault.
Related to e1c5057beee9dab1426ab912048beab85a626e81.

Yao Wei Tjong 姚伟忠 9 years ago
parent
commit
3582dccabb
1 changed files with 21 additions and 16 deletions
  1. 21 16
      Source/Urho3D/IO/FileWatcher.cpp

+ 21 - 16
Source/Urho3D/IO/FileWatcher.cpp

@@ -88,7 +88,7 @@ bool FileWatcher::StartWatching(const String& pathName, bool watchSubDirs)
 #if defined(URHO3D_FILEWATCHER) && defined(URHO3D_THREADING)
 #if defined(URHO3D_FILEWATCHER) && defined(URHO3D_THREADING)
 #ifdef _WIN32
 #ifdef _WIN32
     String nativePath = GetNativePath(RemoveTrailingSlash(pathName));
     String nativePath = GetNativePath(RemoveTrailingSlash(pathName));
-    
+
     dirHandle_ = (void*)CreateFileW(
     dirHandle_ = (void*)CreateFileW(
         WString(nativePath).CString(),
         WString(nativePath).CString(),
         FILE_LIST_DIRECTORY,
         FILE_LIST_DIRECTORY,
@@ -97,13 +97,13 @@ bool FileWatcher::StartWatching(const String& pathName, bool watchSubDirs)
         OPEN_EXISTING,
         OPEN_EXISTING,
         FILE_FLAG_BACKUP_SEMANTICS,
         FILE_FLAG_BACKUP_SEMANTICS,
         0);
         0);
-    
+
     if (dirHandle_ != INVALID_HANDLE_VALUE)
     if (dirHandle_ != INVALID_HANDLE_VALUE)
     {
     {
         path_ = AddTrailingSlash(pathName);
         path_ = AddTrailingSlash(pathName);
         watchSubDirs_ = watchSubDirs;
         watchSubDirs_ = watchSubDirs;
         Run();
         Run();
-        
+
         URHO3D_LOGDEBUG("Started watching path " + pathName);
         URHO3D_LOGDEBUG("Started watching path " + pathName);
         return true;
         return true;
     }
     }
@@ -162,14 +162,14 @@ bool FileWatcher::StartWatching(const String& pathName, bool watchSubDirs)
         URHO3D_LOGERROR("Individual file watching not supported by this OS version, can not start watching path " + pathName);
         URHO3D_LOGERROR("Individual file watching not supported by this OS version, can not start watching path " + pathName);
         return false;
         return false;
     }
     }
-    
+
     watcher_ = CreateFileWatcher(pathName.CString(), watchSubDirs);
     watcher_ = CreateFileWatcher(pathName.CString(), watchSubDirs);
     if (watcher_)
     if (watcher_)
     {
     {
         path_ = AddTrailingSlash(pathName);
         path_ = AddTrailingSlash(pathName);
         watchSubDirs_ = watchSubDirs;
         watchSubDirs_ = watchSubDirs;
         Run();
         Run();
-        
+
         URHO3D_LOGDEBUG("Started watching path " + pathName);
         URHO3D_LOGDEBUG("Started watching path " + pathName);
         return true;
         return true;
     }
     }
@@ -195,8 +195,9 @@ void FileWatcher::StopWatching()
         shouldRun_ = false;
         shouldRun_ = false;
 
 
         // Create and delete a dummy file to make sure the watcher loop terminates
         // Create and delete a dummy file to make sure the watcher loop terminates
-        // This is not required with iNotify
-#if !defined(__linux__)
+        // This is only required on Windows platform
+        // TODO: Remove this temp write approach as it depends on user write privilege
+#ifdef _WIN32
         String dummyFileName = path_ + "dummy.tmp";
         String dummyFileName = path_ + "dummy.tmp";
         File file(context_, dummyFileName, FILE_WRITE);
         File file(context_, dummyFileName, FILE_WRITE);
         file.Close();
         file.Close();
@@ -204,8 +205,11 @@ void FileWatcher::StopWatching()
             fileSystem_->Delete(dummyFileName);
             fileSystem_->Delete(dummyFileName);
 #endif
 #endif
 
 
-        // Remove watch - On linux this will cause read() to return with
-        // the IN_IGNORED flag set
+#if defined(__APPLE__) && !defined(IOS)
+        // Our implementation of file watcher requires the thread to be stopped first before closing the watcher
+        Stop();
+#endif
+
 #ifdef _WIN32
 #ifdef _WIN32
         CloseHandle((HANDLE)dirHandle_);
         CloseHandle((HANDLE)dirHandle_);
 #elif defined(__linux__)
 #elif defined(__linux__)
@@ -215,9 +219,10 @@ void FileWatcher::StopWatching()
 #elif defined(__APPLE__) && !defined(IOS)
 #elif defined(__APPLE__) && !defined(IOS)
         CloseFileWatcher(watcher_);
         CloseFileWatcher(watcher_);
 #endif
 #endif
-        // Join thread *after* removing watch as to avoid getting stuck in
-        // read()
+
+#ifndef __APPLE__
         Stop();
         Stop();
+#endif
 
 
         URHO3D_LOGDEBUG("Stopped watching path " + path_);
         URHO3D_LOGDEBUG("Stopped watching path " + path_);
         path_.Clear();
         path_.Clear();
@@ -235,7 +240,7 @@ void FileWatcher::ThreadFunction()
 #ifdef _WIN32
 #ifdef _WIN32
     unsigned char buffer[BUFFERSIZE];
     unsigned char buffer[BUFFERSIZE];
     DWORD bytesFilled = 0;
     DWORD bytesFilled = 0;
-    
+
     while (shouldRun_)
     while (shouldRun_)
     {
     {
         if (ReadDirectoryChangesW((HANDLE)dirHandle_,
         if (ReadDirectoryChangesW((HANDLE)dirHandle_,
@@ -249,11 +254,11 @@ void FileWatcher::ThreadFunction()
             0))
             0))
         {
         {
             unsigned offset = 0;
             unsigned offset = 0;
-            
+
             while (offset < bytesFilled)
             while (offset < bytesFilled)
             {
             {
                 FILE_NOTIFY_INFORMATION* record = (FILE_NOTIFY_INFORMATION*)&buffer[offset];
                 FILE_NOTIFY_INFORMATION* record = (FILE_NOTIFY_INFORMATION*)&buffer[offset];
-                
+
                 if (record->Action == FILE_ACTION_MODIFIED || record->Action == FILE_ACTION_RENAMED_NEW_NAME)
                 if (record->Action == FILE_ACTION_MODIFIED || record->Action == FILE_ACTION_RENAMED_NEW_NAME)
                 {
                 {
                     String fileName;
                     String fileName;
@@ -261,11 +266,11 @@ void FileWatcher::ThreadFunction()
                     const wchar_t* end = src + record->FileNameLength / 2;
                     const wchar_t* end = src + record->FileNameLength / 2;
                     while (src < end)
                     while (src < end)
                         fileName.AppendUTF8(String::DecodeUTF16(src));
                         fileName.AppendUTF8(String::DecodeUTF16(src));
-                    
+
                     fileName = GetInternalPath(fileName);
                     fileName = GetInternalPath(fileName);
                     AddChange(fileName);
                     AddChange(fileName);
                 }
                 }
-                
+
                 if (!record->NextEntryOffset)
                 if (!record->NextEntryOffset)
                     break;
                     break;
                 else
                 else