Merge pull request #2832 from razzfazz/handle_eintr
authorAlexander Köplinger <alex.koeplinger@outlook.com>
Tue, 5 Apr 2016 19:39:14 +0000 (21:39 +0200)
committerAlexander Köplinger <alex.koeplinger@outlook.com>
Tue, 5 Apr 2016 19:39:14 +0000 (21:39 +0200)
handle EINTR for kevent calls

1  2 
mcs/class/System/System.IO/KeventWatcher.cs

index 8078964da30ea9f5e252b24e710e5131ea7de5b5,5d476a724b39e87962b03ce8bd0659271b3dcfa8..f17eb58d28dca262aeb2205bcaa41468a5183292
@@@ -150,7 -150,7 +150,7 @@@ namespace System.IO 
        [StructLayout(LayoutKind.Sequential)]
        struct timespec {
                public IntPtr tv_sec;
 -              public IntPtr tv_usec;
 +              public IntPtr tv_nsec;
        }
  
        class PathData
  
                        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);
                        }
                }
                                        // 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;
                                }
                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;
  
                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")]
                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)]