FreeBSD Bugzilla – Attachment 166079 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]
patch with fixes to make kevent-based file system monitor work on FreeBSD
patch-mcs_class_System_System.IO_KeventWatcher.cs (text/plain), 6.70 KB, created by
Daniel Becker
on 2016-01-25 03:21:06 UTC
(
hide
)
Description:
patch with fixes to make kevent-based file system monitor work on FreeBSD
Filename:
MIME Type:
Creator:
Daniel Becker
Created:
2016-01-25 03:21:06 UTC
Size:
6.70 KB
patch
obsolete
>From 226b270223c80ddb8b467a7ba20f0bb69b6c7eb7 Mon Sep 17 00:00:00 2001 >From: Daniel Becker <razzfazz@gmail.com> >Date: Sun, 24 Jan 2016 19:05:50 -0800 >Subject: [PATCH] make kevent-based file system monitor work on FreeBSD > >--- > mcs/class/System/System.IO/KeventWatcher.cs | 67 ++++++++++++++++++++--------- > 1 file changed, 46 insertions(+), 21 deletions(-) > >diff --git a/mcs/class/System/System.IO/KeventWatcher.cs b/mcs/class/System/System.IO/KeventWatcher.cs >index 27f61b3..762f273 100644 >--- a/mcs/class/System/System.IO/KeventWatcher.cs >+++ b/mcs/class/System/System.IO/KeventWatcher.cs >@@ -150,7 +150,7 @@ public void Dispose () > [StructLayout(LayoutKind.Sequential)] > struct timespec { > public IntPtr tv_sec; >- public IntPtr tv_usec; >+ public IntPtr tv_nsec; > } > > class PathData >@@ -223,8 +223,8 @@ public void Stop () > conn = -1; > } > >- if (!thread.Join (2000)) >- thread.Abort (); >+ while (!thread.Join (2000)) >+ thread.Interrupt (); > > requestStop = false; > started = false; >@@ -291,11 +291,10 @@ void Setup () > 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; >@@ -304,14 +303,21 @@ void Setup () > > Scan (fullPathNoLastSlash, false, ref initialFds); > >- var immediate_timeout = new timespec { tv_sec = (IntPtr)0, tv_usec = (IntPtr)0 }; >+ var immediate_timeout = new timespec { tv_sec = (IntPtr)0, tv_nsec = (IntPtr)0 }; > 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); > } > } >@@ -361,9 +367,10 @@ void Monitor () > // 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; > } >@@ -395,8 +402,20 @@ void Monitor () > } > > 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 >@@ -584,15 +603,17 @@ void PostEvent (FileAction action, string path, string newPath = null) > 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); >@@ -624,6 +645,7 @@ private string GetFilenameFromFd (int fd) > 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]; > const int maxFds = 200; > >@@ -643,22 +665,25 @@ private string GetFilenameFromFd (int fd) > 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); > >- [DllImport ("libc", EntryPoint="kevent")] >+ [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); > } >
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