[bcl] Break waits in KeventWatcher by closing the command fd instead of polling.
[mono.git] / mcs / class / System / System.IO / KeventWatcher.cs
index dcd0f812149ac988a4d882a4aba6be08eb0db278..5c0f8687789635072ddd2321bda4be0b645c02b0 100644 (file)
@@ -216,6 +216,10 @@ namespace System.IO {
 
                                if (inDispatch)
                                        return;
+                               // This will break the wait in Monitor ()
+                               if (conn != -1)
+                                       close (conn);
+                               conn = -1;
                                if (!thread.Join (2000))
                                        thread.Abort ();
 
@@ -229,10 +233,11 @@ namespace System.IO {
 
                void CleanUp ()
                {
-                       if (conn != -1)
-                               close (conn);
-
-                       conn = -1;
+                       lock (stateLock) {
+                               if (conn != -1)
+                                       close (conn);
+                               conn = -1;
+                       }
 
                        foreach (int fd in fdsDict.Keys)
                                close (fd); 
@@ -279,7 +284,7 @@ namespace System.IO {
                        var initialFds = new List<int> ();
 
                        // fsw.FullPath may end in '/', see https://bugzilla.xamarin.com/show_bug.cgi?id=5747
-                       if (fsw.FullPath.EndsWith ("/", StringComparison.Ordinal))
+                       if (fsw.FullPath != "/" && fsw.FullPath.EndsWith ("/", StringComparison.Ordinal))
                                fullPathNoLastSlash = fsw.FullPath.Substring (0, fsw.FullPath.Length - 1);
                        else
                                fullPathNoLastSlash = fsw.FullPath;
@@ -338,7 +343,6 @@ namespace System.IO {
 
                void Monitor ()
                {
-                       var timeout = new timespec { tv_sec = (IntPtr)0, tv_usec = (IntPtr)500000000 };
                        var eventBuffer = new kevent[32];
                        var newFds = new List<int> ();
                        List<PathData> removeQueue = new List<PathData> ();
@@ -349,9 +353,12 @@ namespace System.IO {
                        while (!requestStop) {
                                var changes = CreateChangeList (ref newFds);
 
-                               int numEvents = kevent (conn, changes, changes.Length, eventBuffer, eventBuffer.Length, ref timeout);
+                               int numEvents = kevent_notimeout (conn, changes, changes.Length, eventBuffer, eventBuffer.Length, IntPtr.Zero);
 
                                if (numEvents == -1) {
+                                       // Stop () signals us to stop by closing the connection
+                                       if (requestStop)
+                                               break;
                                        if (++retries == 3)
                                                throw new IOException (String.Format (
                                                        "persistent kevent() error, error code = '{0}'", Marshal.GetLastWin32Error ()));
@@ -638,6 +645,9 @@ namespace System.IO {
 
                [DllImport ("libc")]
                extern static int kevent (int kq, [In]kevent[] ev, int nchanges, [Out]kevent[] evtlist, int nevents, [In] ref timespec time);
+
+               [DllImport ("libc", EntryPoint="kevent")]
+               extern static int kevent_notimeout (int kq, [In]kevent[] ev, int nchanges, [Out]kevent[] evtlist, int nevents, IntPtr ptr);
        }
 
        class KeventWatcher : IFileWatcher