[FileSystemWatcher] Properly handle multicast delegates.
authorAlexis Christoforides <alexis@thenull.net>
Mon, 15 Dec 2014 15:38:37 +0000 (10:38 -0500)
committerAlexis Christoforides <alexis@thenull.net>
Mon, 15 Dec 2014 16:05:19 +0000 (11:05 -0500)
Reverted the async delegate firing which is how Caching et al. expect FSW events; and properly handle the multicast case.

Also fixing a typo/regression in @2f1a136583c90cae805441e63b94bc4f277bb953

mcs/class/System/System.IO/FileSystemWatcher.cs
mcs/class/System/System.IO/KeventWatcher.cs

index 0d293e53188b4f6155380ba838edf3443f1f7117..43d3c2f362e1f681a13c46a53265585006de6e6a 100644 (file)
@@ -375,60 +375,54 @@ namespace System.IO {
                        ErrorEvent,
                        RenameEvent
                }
-                       
-               protected void OnChanged (FileSystemEventArgs e)
+               private void RaiseEvent (Delegate ev, EventArgs arg, EventType evtype)
                {
-                       if (Changed == null)
+                       if (ev == null)
                                return;
 
-                       if (synchronizingObject == null)
-                               Changed (this, e);
-                       else
-                               synchronizingObject.BeginInvoke (Changed, new object[] { this, e });
+                       if (synchronizingObject == null) {
+                               foreach (var target in ev.GetInvocationList()) {
+                                       switch (evtype) {
+                                       case EventType.RenameEvent:
+                                               ((RenamedEventHandler)target).BeginInvoke (this, (RenamedEventArgs)arg, null, null);
+                                               break;
+                                       case EventType.ErrorEvent:
+                                               ((ErrorEventHandler)target).BeginInvoke (this, (ErrorEventArgs)arg, null, null);
+                                               break;
+                                       case EventType.FileSystemEvent:
+                                               ((FileSystemEventHandler)target).BeginInvoke (this, (FileSystemEventArgs)arg, null, null);
+                                               break;
+                                       }
+                               }
+                               return;
+                       }
+                       
+                       synchronizingObject.BeginInvoke (ev, new object [] {this, arg});
                }
 
-               protected void OnCreated (FileSystemEventArgs e)
+               protected void OnChanged (FileSystemEventArgs e)
                {
-                       if (Created == null)
-                               return;
+                       RaiseEvent (Changed, e, EventType.FileSystemEvent);
+               }
 
-                       if (synchronizingObject == null)
-                               Created (this, e);
-                       else
-                               synchronizingObject.BeginInvoke (Created, new object[] { this, e });
+               protected void OnCreated (FileSystemEventArgs e)
+               {
+                       RaiseEvent (Created, e, EventType.FileSystemEvent);
                }
 
                protected void OnDeleted (FileSystemEventArgs e)
                {
-                       if (Deleted == null)
-                               return;
-
-                       if (synchronizingObject == null)
-                               Deleted (this, e);
-                       else
-                               synchronizingObject.BeginInvoke (Deleted, new object[] { this, e });
+                       RaiseEvent (Deleted, e, EventType.FileSystemEvent);
                }
 
-               internal void OnError (ErrorEventArgs e)
+               protected void OnError (ErrorEventArgs e)
                {
-                       if (Error == null)
-                               return;
-
-                       if (synchronizingObject == null)
-                               Error (this, e);
-                       else
-                               synchronizingObject.BeginInvoke (Error, new object[] { this, e });
+                       RaiseEvent (Error, e, EventType.ErrorEvent);
                }
 
                protected void OnRenamed (RenamedEventArgs e)
                {
-                       if (Renamed == null)
-                               return;
-
-                       if (synchronizingObject == null)
-                               Renamed (this, e);
-                       else
-                               synchronizingObject.BeginInvoke (Renamed, new object[] { this, e });
+                       RaiseEvent (Renamed, e, EventType.RenameEvent);
                }
 
                public WaitForChangedResult WaitForChanged (WatcherChangeTypes changeType)
@@ -458,6 +452,11 @@ namespace System.IO {
                        return result;
                }
 
+               internal void DispatchErrorEvents (ErrorEventArgs args)
+               {
+                       OnError (args);
+               }
+
                internal void DispatchEvents (FileAction act, string filename, ref RenamedEventArgs renamed)
                {
                        if (waiting) {
index 044382b7ef61d8b2e3acebbb3f5bf85c0df67c83..dcd0f812149ac988a4d882a4aba6be08eb0db278 100644 (file)
@@ -252,7 +252,7 @@ namespace System.IO {
                        }
 
                        if (exc != null) {
-                               fsw.OnError (new ErrorEventArgs (exc));
+                               fsw.DispatchErrorEvents (new ErrorEventArgs (exc));
                                return;
                        }
 
@@ -269,7 +269,7 @@ namespace System.IO {
                                        throw exc;
                                }
                                if (exc != null)
-                                       fsw.OnError (new ErrorEventArgs (exc));
+                                       fsw.DispatchErrorEvents (new ErrorEventArgs (exc));
                                requestStop = false;
                        }
                }
@@ -367,7 +367,7 @@ namespace System.IO {
 
                                        if ((kevt.flags & EventFlags.Error) == EventFlags.Error) {
                                                var errMsg = String.Format ("kevent() error watching path '{0}', error code = '{1}'", pathData.Path, kevt.data);
-                                               fsw.OnError (new ErrorEventArgs (new IOException (errMsg)));
+                                               fsw.DispatchErrorEvents (new ErrorEventArgs (new IOException (errMsg)));
                                                continue;
                                        }
                                                
@@ -415,7 +415,7 @@ namespace System.IO {
                        var fd = open (path, O_EVTONLY, 0);
 
                        if (fd == -1) {
-                               fsw.OnError (new ErrorEventArgs (new IOException (String.Format (
+                               fsw.DispatchErrorEvents (new ErrorEventArgs (new IOException (String.Format (
                                        "open() error while attempting to process path '{0}', error code = '{1}'", path, Marshal.GetLastWin32Error ()))));
                                return null;
                        }
@@ -440,7 +440,7 @@ namespace System.IO {
                                return pathData;
                        } catch (Exception e) {
                                close (fd);
-                               fsw.OnError (new ErrorEventArgs (e));
+                               fsw.DispatchErrorEvents (new ErrorEventArgs (e));
                                return null;
                        }
 
@@ -576,10 +576,8 @@ namespace System.IO {
                                string newName = newPath.Substring (fullPathNoLastSlash.Length + 1);
                                renamed = new RenamedEventArgs (WatcherChangeTypes.Renamed, fsw.Path, newName, name);
                        }
-
-                       inDispatch = true;
-                       fsw.DispatchEvents (action, path, ref renamed);
-                       inDispatch = false;
+                               
+                       fsw.DispatchEvents (action, name, ref renamed);
 
                        if (fsw.Waiting) {
                                lock (fsw) {
@@ -599,7 +597,7 @@ namespace System.IO {
 
                                return sb.ToString ();
                        } else {
-                               fsw.OnError (new ErrorEventArgs (new IOException (String.Format (
+                               fsw.DispatchErrorEvents (new ErrorEventArgs (new IOException (String.Format (
                                        "fcntl() error while attempting to get path for fd '{0}', error code = '{1}'", fd, Marshal.GetLastWin32Error ()))));
                                return String.Empty;
                        }