[xbuild] Fix ProcessWrapper to WaitForExit(..) before accessing ExitCode
[mono.git] / mono / metadata / filewatcher.c
index c0c37bc45b22ecec123aeae5af9ba6b60ed67893..eb1827a0c6055f863341ad2c12cdcf55b11ec600 100644 (file)
@@ -5,12 +5,23 @@
  *     Gonzalo Paniagua Javier (gonzalo@ximian.com)
  *
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_EVENT_H
+#include <sys/event.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/exception.h>
 #include <mono/metadata/filewatcher.h>
@@ -51,22 +62,17 @@ ves_icall_System_IO_FSW_SupportsFSW (void)
        MonoDl *fam_module;
        int lib_used = 4; /* gamin */
        int inotify_instance;
-       void *iter;
        char *err;
 
-       MONO_ARCH_SAVE_REGS;
-
        inotify_instance = ves_icall_System_IO_InotifyWatcher_GetInotifyInstance ();
        if (inotify_instance != -1) {
                close (inotify_instance);
                return 5; /* inotify */
        }
 
-       iter = NULL;
        fam_module = mono_dl_open ("libgamin-1.so", MONO_DL_LAZY, NULL);
        if (fam_module == NULL) {
                lib_used = 2; /* FAM */
-               iter = NULL;
                fam_module = mono_dl_open ("libfam.so", MONO_DL_LAZY, NULL);
        }
 
@@ -104,8 +110,6 @@ ves_icall_System_IO_FAMW_InternalFAMNextEvent (gpointer conn,
 {
        FAMEvent ev;
 
-       MONO_ARCH_SAVE_REGS;
-
        if (FAMNextEvent (conn, &ev) == 1) {
                *filename = mono_string_new (mono_domain_get (), ev.filename);
                *code = ev.code;
@@ -117,35 +121,7 @@ ves_icall_System_IO_FAMW_InternalFAMNextEvent (gpointer conn,
 }
 #endif
 
-#if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) && !defined(__NR_inotify_init)
-#  if defined(__i386__)
-#     define __NR_inotify_init         291
-#  elif defined(__x86_64__)
-#     define __NR_inotify_init         253
-#  elif defined(__ppc__) || defined(__powerpc__) || defined(__powerpc64__)
-#     define __NR_inotify_init         275
-#  elif defined (__s390__) || defined (__s390x__)
-#     define __NR_inotify_init         284
-#  elif defined(__sparc__) || defined (__sparc64__)
-#     define __NR_inotify_init         151
-#  elif defined (__ia64__)
-#     define __NR_inotify_init         1277
-#  elif defined (__arm__)
-#     define __NR_inotify_init         316
-#  elif defined(__alpha__)
-#     define __NR_inotify_init         444
-#  endif
-#ifdef __NR_inotify_init
-#  ifndef __NR_inotify_add_watch
-#    define __NR_inotify_add_watch (__NR_inotify_init + 1)
-#  endif
-#  ifndef __NR_inotify_rm_watch
-#    define __NR_inotify_rm_watch (__NR_inotify_init + 2)
-#  endif
-#endif
-#endif
-
-#if !defined(__linux__) || !defined(__NR_inotify_init)
+#ifndef HAVE_SYS_INOTIFY_H
 int ves_icall_System_IO_InotifyWatcher_GetInotifyInstance ()
 {
        return -1;
@@ -161,12 +137,13 @@ int ves_icall_System_IO_InotifyWatcher_RemoveWatch (int fd, gint32 watch_descrip
        return -1;
 }
 #else
+#include <sys/inotify.h>
 #include <errno.h>
 
 int
 ves_icall_System_IO_InotifyWatcher_GetInotifyInstance ()
 {
-       return syscall (__NR_inotify_init);
+       return inotify_init ();
 }
 
 int
@@ -175,8 +152,6 @@ ves_icall_System_IO_InotifyWatcher_AddWatch (int fd, MonoString *name, gint32 ma
        char *str, *path;
        int retval;
 
-       MONO_ARCH_SAVE_REGS;
-
        if (name == NULL)
                return -1;
 
@@ -185,7 +160,7 @@ ves_icall_System_IO_InotifyWatcher_AddWatch (int fd, MonoString *name, gint32 ma
        if (!path)
                path = str;
 
-       retval = syscall (__NR_inotify_add_watch, fd, path, mask);
+       retval = inotify_add_watch (fd, path, mask);
        if (retval < 0) {
                switch (errno) {
                case EACCES:
@@ -221,7 +196,58 @@ ves_icall_System_IO_InotifyWatcher_AddWatch (int fd, MonoString *name, gint32 ma
 int
 ves_icall_System_IO_InotifyWatcher_RemoveWatch (int fd, gint32 watch_descriptor)
 {
-       return syscall (__NR_inotify_rm_watch, fd, watch_descriptor);
+       return inotify_rm_watch (fd, watch_descriptor);
 }
 #endif
 
+#if HAVE_KQUEUE
+
+static void
+interrupt_kevent (gpointer data)
+{
+       int *kq_ptr = data;
+
+       /* Interrupt the kevent () call by closing the fd */
+       close (*kq_ptr);
+       /* Signal to managed code that the fd is closed */
+       *kq_ptr = -1;
+}
+
+/*
+ * ves_icall_System_IO_KqueueMonitor_kevent_notimeout:
+ *
+ *   Call kevent (), while handling runtime interruptions.
+ */
+int
+ves_icall_System_IO_KqueueMonitor_kevent_notimeout (int *kq_ptr, gpointer changelist, int nchanges, gpointer eventlist, int nevents)
+{
+       int res;
+       gboolean interrupted;
+
+       mono_thread_info_install_interrupt (interrupt_kevent, kq_ptr, &interrupted);
+       if (interrupted) {
+               close (*kq_ptr);
+               *kq_ptr = -1;
+               return -1;
+       }
+
+       MONO_PREPARE_BLOCKING;
+       res = kevent (*kq_ptr, changelist, nchanges, eventlist, nevents, NULL);
+       MONO_FINISH_BLOCKING;
+
+       mono_thread_info_uninstall_interrupt (&interrupted);
+
+       return res;
+}
+
+#else
+
+int
+ves_icall_System_IO_KqueueMonitor_kevent_notimeout (int *kq_ptr, gpointer changelist, int nchanges, gpointer eventlist, int nevents)
+{
+       g_assert_not_reached ();
+       return -1;
+}
+
+#endif /* #if HAVE_KQUEUE */
+