Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / metadata / filewatcher.c
index 664b28a05275b7bf3e68ec29e248736ca4c8ba37..159a2537bcbf05459238ba5491a5a46be6816946 100644 (file)
@@ -1,22 +1,36 @@
-/*
- * filewatcher.c: File System Watcher internal calls
+/**
+ * \file
+ * File System Watcher internal calls
  *
  * Authors:
  *     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>
 #include <mono/metadata/marshal.h>
 #include <mono/utils/mono-dl.h>
 #include <mono/utils/mono-io-portability.h>
+#include <mono/metadata/w32error.h>
+
 #ifdef HOST_WIN32
 
 /*
@@ -97,12 +111,15 @@ ves_icall_System_IO_FAMW_InternalFAMNextEvent (gpointer conn,
                                               gint *code,
                                               gint *reqnum)
 {
+       MonoError error;
        FAMEvent ev;
 
        if (FAMNextEvent (conn, &ev) == 1) {
-               *filename = mono_string_new (mono_domain_get (), ev.filename);
+               *filename = mono_string_new_checked (mono_domain_get (), ev.filename, &error);
                *code = ev.code;
                *reqnum = ev.fr.reqnum;
+               if (mono_error_set_pending_exception (&error))
+                       return FALSE;
                return TRUE;
        }
 
@@ -138,13 +155,16 @@ ves_icall_System_IO_InotifyWatcher_GetInotifyInstance ()
 int
 ves_icall_System_IO_InotifyWatcher_AddWatch (int fd, MonoString *name, gint32 mask)
 {
+       MonoError error;
        char *str, *path;
        int retval;
 
        if (name == NULL)
                return -1;
 
-       str = mono_string_to_utf8 (name);
+       str = mono_string_to_utf8_checked (name, &error);
+       if (mono_error_set_pending_exception (&error))
+               return -1;
        path = mono_portability_find_file (str, TRUE);
        if (!path)
                path = str;
@@ -188,3 +208,55 @@ ves_icall_System_IO_InotifyWatcher_RemoveWatch (int fd, gint32 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_ENTER_GC_SAFE;
+       res = kevent (*kq_ptr, changelist, nchanges, eventlist, nevents, NULL);
+       MONO_EXIT_GC_SAFE;
+
+       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 */
+