FreeBSD Bugzilla – Attachment 173875 Details for
Bug 206593
lang/mono: fix kevent-based file system monitor on FreeBSD
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
updated patch for version 4.4.2.11
patch-mcs_class_System_System.IO_KeventWatcher.cs (text/plain), 6.83 KB, created by
Daniel Becker
on 2016-08-19 21:36:57 UTC
(
hide
)
Description:
updated patch for version 4.4.2.11
Filename:
MIME Type:
Creator:
Daniel Becker
Created:
2016-08-19 21:36:57 UTC
Size:
6.83 KB
patch
obsolete
>--- mcs/class/System/System.IO/KeventWatcher.cs.orig 2016-08-12 00:23:56.495779000 -0700 >+++ mcs/class/System/System.IO/KeventWatcher.cs 2016-08-12 00:33:47.735735590 -0700 >@@ -232,8 +232,8 @@ > conn = -1; > } > >- if (!thread.Join (2000)) >- thread.Abort (); >+ while (!thread.Join (2000)) >+ thread.Interrupt (); > > requestStop = false; > started = false; >@@ -300,11 +300,10 @@ > else > fullPathNoLastSlash = fsw.FullPath; > >- // GetFilenameFromFd() returns the *realpath* which can be different than fsw.FullPath because symlinks. >+ // realpath() returns the *realpath* which can be different than fsw.FullPath because symlinks. > // If so, introduce a fixup step. >- int fd = open (fullPathNoLastSlash, O_EVTONLY, 0); >- var resolvedFullPath = GetFilenameFromFd (fd); >- close (fd); >+ var sb = new StringBuilder (__DARWIN_MAXPATHLEN); >+ var resolvedFullPath = (realpath(fsw.FullPath, sb) == IntPtr.Zero) ? "" : sb.ToString(); > > if (resolvedFullPath != fullPathNoLastSlash) > fixupPath = resolvedFullPath; >@@ -317,10 +316,17 @@ > var eventBuffer = new kevent[0]; // we don't want to take any events from the queue at this point > var changes = CreateChangeList (ref initialFds); > >- int numEvents = kevent (conn, changes, changes.Length, eventBuffer, eventBuffer.Length, ref immediate_timeout); >+ int numEvents; >+ int errno = 0; >+ do { >+ numEvents = kevent (conn, changes, changes.Length, eventBuffer, eventBuffer.Length, ref immediate_timeout); >+ if (numEvents == -1) { >+ errno = Marshal.GetLastWin32Error (); >+ } >+ } while (numEvents == -1 && errno == EINTR); > > if (numEvents == -1) { >- var errMsg = String.Format ("kevent() error at initial event registration, error code = '{0}'", Marshal.GetLastWin32Error ()); >+ var errMsg = String.Format ("kevent() error at initial event registration, error code = '{0}'", errno); > throw new IOException (errMsg); > } > } >@@ -364,32 +370,20 @@ > while (!requestStop) { > var changes = CreateChangeList (ref newFds); > >- // We are calling an icall, so have to marshal manually >- // Marshal in >- int ksize = Marshal.SizeOf<kevent> (); >- var changesNative = Marshal.AllocHGlobal (ksize * changes.Length); >- for (int i = 0; i < changes.Length; ++i) >- Marshal.StructureToPtr (changes [i], changesNative + (i * ksize), false); >- var eventBufferNative = Marshal.AllocHGlobal (ksize * eventBuffer.Length); >- >- int numEvents = kevent_notimeout (ref conn, changesNative, changes.Length, eventBufferNative, eventBuffer.Length); >- >- // Marshal out >- Marshal.FreeHGlobal (changesNative); >- for (int i = 0; i < numEvents; ++i) >- eventBuffer [i] = Marshal.PtrToStructure<kevent> (eventBufferNative + (i * ksize)); >- Marshal.FreeHGlobal (eventBufferNative); >+ 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) >+ int errno = Marshal.GetLastWin32Error (); >+ if (errno != EINTR && ++retries == 3) > throw new IOException (String.Format ( >- "persistent kevent() error, error code = '{0}'", Marshal.GetLastWin32Error ())); >+ "persistent kevent() error, error code = '{0}'", errno)); > > continue; > } >+ > retries = 0; > > for (var i = 0; i < numEvents; i++) { >@@ -417,8 +411,20 @@ > } > > if ((kevt.fflags & FilterFlags.VNodeRename) == FilterFlags.VNodeRename) { >- UpdatePath (pathData); >- } >+ /* We can simply remove the entire subtree here, as >+ the move will trigger a directory update and thus >+ a re-scan at the new location, which will cause any >+ children to be re-added. */ >+ removeQueue.Add (pathData); >+ if (pathData.IsDirectory) { >+ var prefix = pathData.Path + Path.DirectorySeparatorChar; >+ foreach (var path in pathsDict.Keys) >+ if (path.StartsWith (prefix)) { >+ removeQueue.Add (pathsDict [path]); >+ } >+ } >+ PostEvent (FileAction.RenamedOldName, pathData.Path); >+ } > > if ((kevt.fflags & FilterFlags.VNodeWrite) == FilterFlags.VNodeWrite) { > if (pathData.IsDirectory) //TODO: Check if dirs trigger Changed events on .NET >@@ -606,15 +612,17 @@ > return; > > // e.Name >- string name = path.Substring (fullPathNoLastSlash.Length + 1); >+ string name = (path.Length > fullPathNoLastSlash.Length) ? path.Substring (fullPathNoLastSlash.Length + 1) : String.Empty; > > // only post events that match filter pattern. check both old and new paths for renames > if (!fsw.Pattern.IsMatch (path) && (newPath == null || !fsw.Pattern.IsMatch (newPath))) > return; > > if (action == FileAction.RenamedNewName) { >- string newName = newPath.Substring (fullPathNoLastSlash.Length + 1); >+ string newName = (newPath.Length > fullPathNoLastSlash.Length) ? newPath.Substring (fullPathNoLastSlash.Length + 1) : String.Empty; > renamed = new RenamedEventArgs (WatcherChangeTypes.Renamed, fsw.Path, newName, name); >+ } else if (action == FileAction.RenamedOldName) { >+ renamed = new RenamedEventArgs (WatcherChangeTypes.Renamed, fsw.Path, null, name); > } > > fsw.DispatchEvents (action, name, ref renamed); >@@ -646,6 +654,7 @@ > const int O_EVTONLY = 0x8000; > const int F_GETPATH = 50; > const int __DARWIN_MAXPATHLEN = 1024; >+ const int EINTR = 4; > static readonly kevent[] emptyEventList = new System.IO.kevent[0]; > int maxFds = Int32.MaxValue; > >@@ -665,23 +674,26 @@ > string fixupPath = null; > string fullPathNoLastSlash = null; > >- [DllImport ("libc", EntryPoint="fcntl", CharSet=CharSet.Auto, SetLastError=true)] >+ [DllImport ("libc", CharSet=CharSet.Auto, SetLastError=true)] > static extern int fcntl (int file_names_by_descriptor, int cmd, StringBuilder sb); > >- [DllImport ("libc")] >+ [DllImport ("libc", SetLastError=true)] > extern static int open (string path, int flags, int mode_t); > >+ [DllImport ("libc", CharSet=CharSet.Auto, SetLastError=true)] >+ static extern IntPtr realpath (string pathname, StringBuilder sb); >+ > [DllImport ("libc")] > extern static int close (int fd); > >- [DllImport ("libc")] >+ [DllImport ("libc", SetLastError=true)] > extern static int kqueue (); > >- [DllImport ("libc")] >+ [DllImport ("libc", SetLastError=true)] > extern static int kevent (int kq, [In]kevent[] ev, int nchanges, [Out]kevent[] evtlist, int nevents, [In] ref timespec time); > >- [MethodImplAttribute(MethodImplOptions.InternalCall)] >- extern static int kevent_notimeout (ref int kq, IntPtr ev, int nchanges, IntPtr evtlist, int nevents); >+ [DllImport ("libc", EntryPoint="kevent", SetLastError=true)] >+ extern static int kevent_notimeout (int kq, [In]kevent[] ev, int nchanges, [Out]kevent[] evtlist, int nevents, IntPtr ptr); > } > > class KeventWatcher : IFileWatcher
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 206593
:
166079
|
173875
|
176608