summaryrefslogtreecommitdiff
path: root/lang/mono/files/patch-mcs_class_System_System.IO_KeventWatcher.cs
diff options
context:
space:
mode:
Diffstat (limited to 'lang/mono/files/patch-mcs_class_System_System.IO_KeventWatcher.cs')
-rw-r--r--lang/mono/files/patch-mcs_class_System_System.IO_KeventWatcher.cs196
1 files changed, 196 insertions, 0 deletions
diff --git a/lang/mono/files/patch-mcs_class_System_System.IO_KeventWatcher.cs b/lang/mono/files/patch-mcs_class_System_System.IO_KeventWatcher.cs
new file mode 100644
index 000000000000..63a16f16c45e
--- /dev/null
+++ b/lang/mono/files/patch-mcs_class_System_System.IO_KeventWatcher.cs
@@ -0,0 +1,196 @@
+
+$FreeBSD$
+
+https://bugzilla.novell.com/show_bug.cgi?id=542485
+
+--- mcs/class/System/System.IO/KeventWatcher.cs.orig
++++ mcs/class/System/System.IO/KeventWatcher.cs
+@@ -38,11 +38,11 @@
+ namespace System.IO {
+
+ struct kevent : IDisposable {
+- public int ident;
++ public IntPtr ident;
+ public short filter;
+ public ushort flags;
+ public uint fflags;
+- public int data;
++ public IntPtr data;
+ public IntPtr udata;
+
+ public void Dispose ()
+@@ -53,8 +53,8 @@
+ }
+
+ struct timespec {
+- public int tv_sec;
+- public int tv_usec;
++ public IntPtr tv_sec;
++ public IntPtr tv_usec;
+ }
+
+ class KeventFileData {
+@@ -88,6 +88,31 @@
+ static Thread thread;
+ static int conn;
+ static bool stop;
++
++ /* Flags */
++
++ const int EV_ADD = 0x0001; /* add event to kq (implies enable) */
++ const int EV_DELETE = 0x0002; /* delete event from kq */
++ const int EV_ENABLE = 0x0004; /* enable event */
++ const int EV_DISABLE = 0x0008; /* disable event (not reported) */
++ const int EV_ONESHOT = 0x0010; /* only report one occurrence */
++ const int EV_CLEAR = 0x0020; /* clear event state after reporting */
++ const int EV_EOF = 0x8000; /* EOF detected */
++ const int EV_ERROR = 0x4000; /* error, data contains errno */
++
++ /* System defined filters */
++ const int EVFILT_READ = -1;
++ const int EVFILT_VNODE = -4; /* attached to vnodes */
++
++ /* Events */
++
++ const int NOTE_DELETE = 0x0001; /* vnode was removed */
++ const int NOTE_WRITE = 0x0002; /* data contents changed */
++ const int NOTE_EXTEND = 0x0004; /* size increased */
++ const int NOTE_ATTRIB = 0x0008; /* attributes changed */
++ const int NOTE_LINK = 0x0010; /* link count changed */
++ const int NOTE_RENAME = 0x0020; /* vnode was renamed */
++ const int NOTE_REVOKE = 0x0040; /* vnode access was revoked */
+
+ private KeventWatcher ()
+ {
+@@ -142,9 +167,9 @@
+
+ data.Enabled = true;
+ lock (this) {
++ stop = false;
+ StartMonitoringDirectory (data);
+ watches [fsw] = data;
+- stop = false;
+ }
+ }
+ }
+@@ -162,20 +187,23 @@
+ kevent ev = new kevent();
+ ev.udata = IntPtr.Zero;
+ timespec nullts = new timespec();
+- nullts.tv_sec = 0;
+- nullts.tv_usec = 0;
++ nullts.tv_sec = IntPtr.Zero;
++ nullts.tv_usec = IntPtr.Zero;
+ if (fd > 0) {
+- ev.ident = fd;
+- ev.filter = -4;
+- ev.flags = 1 | 4 | 20;
+- ev.fflags = 20 | 2 | 1 | 8;
+- ev.data = 0;
++ ev.ident = (IntPtr)fd;
++ ev.filter = EVFILT_VNODE;
++ ev.flags = EV_ADD | EV_ENABLE | EV_CLEAR;
++ ev.fflags = NOTE_RENAME | NOTE_WRITE | NOTE_DELETE | NOTE_ATTRIB;
++ ev.data = IntPtr.Zero;
+ ev.udata = Marshal.StringToHGlobalAuto (data.Directory);
+ kevent outev = new kevent();
+ outev.udata = IntPtr.Zero;
+- kevent (conn, ref ev, 1, ref outev, 0, ref nullts);
++ int ret = kevent (conn, ref ev, 1, ref outev, 0, ref nullts);
++ if ((ret == -1) || ((ev.flags & EV_ERROR) > 0)) {
++ return;
++ }
+ data.ev = ev;
+- requests [fd] = data;
++ requests [(IntPtr)fd] = data;
+ }
+
+ if (!data.IncludeSubdirs)
+@@ -204,31 +232,35 @@
+
+ static void StopMonitoringDirectory (KeventData data)
+ {
+- close(data.ev.ident);
++ close((int)(data.ev.ident));
+ }
+
+ void Monitor ()
+ {
+-
++
+ while (!stop) {
+ kevent ev = new kevent();
+ ev.udata = IntPtr.Zero;
+ kevent nullev = new kevent();
+ nullev.udata = IntPtr.Zero;
+ timespec ts = new timespec();
+- ts.tv_sec = 0;
+- ts.tv_usec = 0;
++ ts.tv_sec = IntPtr.Zero;
++ ts.tv_usec = IntPtr.Zero;
+ int haveEvents;
+ lock (this) {
+ haveEvents = kevent (conn, ref nullev, 0, ref ev, 1, ref ts);
+ }
+
+- if (haveEvents > 0) {
+- // Restart monitoring
+- KeventData data = (KeventData) requests [ev.ident];
+- StopMonitoringDirectory (data);
+- StartMonitoringDirectory (data);
+- ProcessEvent (ev);
++ if (haveEvents != 0) {
++ if ((haveEvents == -1) || ((ev.flags & EV_ERROR) > 0)) {
++ Error ();
++ } else {
++ // Restart monitoring
++ KeventData data = (KeventData) requests [(IntPtr)(ev.ident)];
++ StopMonitoringDirectory (data);
++ StartMonitoringDirectory (data);
++ ProcessEvent (ev);
++ }
+ } else {
+ System.Threading.Thread.Sleep (500);
+ }
+@@ -240,10 +272,18 @@
+ }
+ }
+
++ void Error ()
++ {
++ // Something went wrong. Stop the thread.
++ lock (this) {
++ stop = true;
++ }
++ }
++
+ void ProcessEvent (kevent ev)
+ {
+ lock (this) {
+- KeventData data = (KeventData) requests [ev.ident];
++ KeventData data = (KeventData) requests [(IntPtr)(ev.ident)];
+ if (!data.Enabled)
+ return;
+
+@@ -265,7 +305,7 @@
+ data.DirEntries [fsi.FullName] = new KeventFileData(fsi, fsi.LastAccessTime, fsi.LastWriteTime);
+ if (fsw.IncludeSubdirectories && fsi is DirectoryInfo) {
+ data.Directory = filename;
+- requests [ev.ident] = data;
++ requests [(IntPtr)(ev.ident)] = data;
+ ProcessEvent(ev);
+ }
+ PostEvent(filename, fsw, fa, changedFsi);
+@@ -348,10 +388,10 @@
+ [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 kqueue, ref kevent ev, int nchanges, ref kevent evtlist, int nevents, ref timespec ts);
+ }
+ }