2007-09-02 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / io-layer / handles.c
index 19f28646a8416f5f06c4e2e9eb48e7b9192764b8..7e9c173ceaab42ed5a51c0f0f6a05ac85cdbb365 100644 (file)
@@ -4,7 +4,7 @@
  * Author:
  *     Dick Porter (dick@ximian.com)
  *
- * (C) 2002 Ximian, Inc.
+ * (C) 2002-2006 Novell, Inc.
  */
 
 #include <config.h>
@@ -29,6 +29,8 @@
 #include <mono/io-layer/misc-private.h>
 #include <mono/io-layer/shared.h>
 #include <mono/io-layer/collection.h>
+#include <mono/io-layer/process-private.h>
+#include <mono/io-layer/critical-section-private.h>
 
 #undef DEBUG
 #undef DEBUG_REFS
@@ -50,6 +52,7 @@ static struct _WapiHandleOps *handle_ops[WAPI_HANDLE_COUNT]={
        &_wapi_pipe_ops,
        &_wapi_namedmutex_ops,
        &_wapi_namedsem_ops,
+       &_wapi_namedevent_ops,
 };
 
 static void _wapi_shared_details (gpointer handle_info);
@@ -68,6 +71,7 @@ static void (*handle_details[WAPI_HANDLE_COUNT])(gpointer) = {
        _wapi_pipe_details,
        _wapi_shared_details,   /* namedmutex */
        _wapi_shared_details,   /* namedsem */
+       _wapi_shared_details,   /* namedevent */
 };
 
 const char *_wapi_handle_typename[] = {
@@ -84,6 +88,7 @@ const char *_wapi_handle_typename[] = {
        "Pipe",
        "N.Mutex",
        "N.Sem",
+       "N.Event",
        "Error!!"
 };
 
@@ -106,9 +111,97 @@ mono_mutex_t _wapi_global_signal_mutex;
 pthread_cond_t _wapi_global_signal_cond;
 
 int _wapi_sem_id;
+gboolean _wapi_has_shut_down = FALSE;
+
+/* Use this instead of getpid(), to cope with linuxthreads.  It's a
+ * function rather than a variable lookup because we need to get at
+ * this before share_init() might have been called.
+ */
+static pid_t _wapi_pid;
+static mono_once_t pid_init_once = MONO_ONCE_INIT;
+
+static void pid_init (void)
+{
+       _wapi_pid = getpid ();
+}
+
+pid_t _wapi_getpid (void)
+{
+       mono_once (&pid_init_once, pid_init);
+       
+       return(_wapi_pid);
+}
+
 
 static mono_mutex_t scan_mutex = MONO_MUTEX_INITIALIZER;
 
+static void handle_cleanup (void)
+{
+       int i, j, k;
+       
+       _wapi_process_signal_self ();
+
+       /* Every shared handle we were using ought really to be closed
+        * by now, but to make sure just blow them all away.  The
+        * exiting finalizer thread in particular races us to the
+        * program exit and doesn't always win, so it can be left
+        * cluttering up the shared file.  Anything else left over is
+        * really a bug.
+        */
+       for(i = SLOT_INDEX (0); _wapi_private_handles[i] != NULL; i++) {
+               for(j = SLOT_OFFSET (0); j < _WAPI_HANDLE_INITIAL_COUNT; j++) {
+                       struct _WapiHandleUnshared *handle_data = &_wapi_private_handles[i][j];
+                       int type = handle_data->type;
+                       
+                       
+                       if (_WAPI_SHARED_HANDLE (type)) {
+                               gpointer handle = GINT_TO_POINTER (i*_WAPI_HANDLE_INITIAL_COUNT+j);
+                               
+                               if (type == WAPI_HANDLE_THREAD) {
+                                       /* Special-case thread handles
+                                        * because they need extra
+                                        * cleanup.  This also avoids
+                                        * a race condition between
+                                        * the application exit and
+                                        * the finalizer thread - if
+                                        * it finishes up between now
+                                        * and actual app termination
+                                        * it will find all its handle
+                                        * details have been blown
+                                        * away, so this sets those
+                                        * anyway.
+                                        */
+                                       _wapi_thread_set_termination_details (handle, 0);
+                               }
+                               
+                               for(k = handle_data->ref; k > 0; k--) {
+#ifdef DEBUG
+                                       g_message ("%s: unreffing %s handle %p", __func__, _wapi_handle_typename[type], handle);
+#endif
+                                       
+                                       _wapi_handle_unref (handle);
+                               }
+                       }
+               }
+       }
+       
+       _wapi_shm_semaphores_remove ();
+
+       mono_mutex_destroy(&_wapi_global_signal_mutex);
+       pthread_cond_destroy(&_wapi_global_signal_cond);
+}
+
+void _wapi_cleanup ()
+{
+       g_assert (_wapi_has_shut_down == FALSE);
+       
+       _wapi_has_shut_down = TRUE;
+
+       _wapi_critical_section_cleanup ();
+       _wapi_error_cleanup ();
+       _wapi_thread_cleanup ();
+}
+
 static mono_once_t shared_init_once = MONO_ONCE_INIT;
 static void shared_init (void)
 {
@@ -126,11 +219,11 @@ static void shared_init (void)
 
                _wapi_private_handle_count += _WAPI_HANDLE_INITIAL_COUNT;
        } while(_wapi_fd_reserve > _wapi_private_handle_count);
+
+       _wapi_shm_semaphores_init ();
        
        _wapi_shared_layout = _wapi_shm_attach (WAPI_SHM_DATA);
        g_assert (_wapi_shared_layout != NULL);
-
-       _wapi_shm_semaphores_init ();
        
        _wapi_fileshare_layout = _wapi_shm_attach (WAPI_SHM_FILESHARE);
        g_assert (_wapi_fileshare_layout != NULL);
@@ -142,12 +235,21 @@ static void shared_init (void)
        
        thr_ret = mono_mutex_init(&_wapi_global_signal_mutex, NULL);
        g_assert (thr_ret == 0);
+
+       /* Using g_atexit here instead of an explicit function call in
+        * a cleanup routine lets us cope when a third-party library
+        * calls exit (eg if an X client loses the connection to its
+        * server.)
+        */
+       g_atexit (handle_cleanup);
 }
 
 static void _wapi_handle_init_shared (struct _WapiHandleShared *handle,
                                      WapiHandleType type,
                                      gpointer handle_specific)
 {
+       g_assert (_wapi_has_shut_down == FALSE);
+       
        handle->type = type;
        handle->timestamp = (guint32)(time (NULL) & 0xFFFFFFFF);
        handle->signalled = FALSE;
@@ -163,6 +265,8 @@ static void _wapi_handle_init (struct _WapiHandleUnshared *handle,
 {
        int thr_ret;
        
+       g_assert (_wapi_has_shut_down == FALSE);
+       
        handle->type = type;
        handle->signalled = FALSE;
        handle->ref = 1;
@@ -188,6 +292,8 @@ static guint32 _wapi_handle_new_shared (WapiHandleType type,
        static guint32 last = 1;
        int thr_ret;
        
+       g_assert (_wapi_has_shut_down == FALSE);
+       
        /* Leave the first slot empty as a guard */
 again:
        /* FIXME: expandable array */
@@ -243,6 +349,8 @@ static guint32 _wapi_handle_new_internal (WapiHandleType type,
        static guint32 last = 0;
        gboolean retry = FALSE;
        
+       g_assert (_wapi_has_shut_down == FALSE);
+       
        /* A linear scan should be fast enough.  Start from the last
         * allocation, assuming that handles are allocated more often
         * than they're freed. Leave the space reserved for file
@@ -288,6 +396,8 @@ gpointer _wapi_handle_new (WapiHandleType type, gpointer handle_specific)
        gpointer handle;
        int thr_ret;
        
+       g_assert (_wapi_has_shut_down == FALSE);
+       
        mono_once (&shared_init_once, shared_init);
        
 #ifdef DEBUG
@@ -305,15 +415,25 @@ gpointer _wapi_handle_new (WapiHandleType type, gpointer handle_specific)
        while ((handle_idx = _wapi_handle_new_internal (type, handle_specific)) == 0) {
                /* Try and expand the array, and have another go */
                int idx = SLOT_INDEX (_wapi_private_handle_count);
+               if (idx >= _WAPI_PRIVATE_MAX_SLOTS) {
+                       break;
+               }
+               
                _wapi_private_handles [idx] = g_new0 (struct _WapiHandleUnshared,
                                                _WAPI_HANDLE_INITIAL_COUNT);
 
                _wapi_private_handle_count += _WAPI_HANDLE_INITIAL_COUNT;
        }
-
+       
        thr_ret = mono_mutex_unlock (&scan_mutex);
        g_assert (thr_ret == 0);
        pthread_cleanup_pop (0);
+
+       if (handle_idx == 0) {
+               /* We ran out of slots */
+               handle = _WAPI_HANDLE_INVALID;
+               goto done;
+       }
                
        /* Make sure we left the space for fd mappings */
        g_assert (handle_idx >= _wapi_fd_reserve);
@@ -359,6 +479,8 @@ gpointer _wapi_handle_new_from_offset (WapiHandleType type, guint32 offset,
        struct _WapiHandleShared *shared;
        guint32 now = (guint32)(time (NULL) & 0xFFFFFFFF);
        
+       g_assert (_wapi_has_shut_down == FALSE);
+       
        mono_once (&shared_init_once, shared_init);
 
 #ifdef DEBUG
@@ -373,7 +495,7 @@ gpointer _wapi_handle_new_from_offset (WapiHandleType type, guint32 offset,
        shared = &_wapi_shared_layout->handles[offset];
        if (timestamp) {
                /* Bump up the timestamp for this offset */
-               InterlockedExchange (&shared->timestamp, now);
+               InterlockedExchange ((gint32 *)&shared->timestamp, now);
        }
                
        pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
@@ -414,6 +536,19 @@ first_pass_done:
        
        if (shared->type == WAPI_HANDLE_UNUSED) {
                /* Someone deleted this handle while we were working */
+#ifdef DEBUG
+               g_message ("%s: Handle at 0x%x unused", __func__, offset);
+#endif
+               goto done;
+       }
+
+       if (shared->type != type) {
+#ifdef DEBUG
+               g_message ("%s: Wrong type at %d 0x%x! Found %s wanted %s",
+                          __func__, offset, offset,
+                          _wapi_handle_typename[shared->type],
+                          _wapi_handle_typename[type]);
+#endif
                goto done;
        }
        
@@ -441,11 +576,10 @@ first_pass_done:
        handle = GUINT_TO_POINTER (handle_idx);
                
        _WAPI_PRIVATE_HANDLES(handle_idx).u.shared.offset = offset;
-       InterlockedIncrement (&shared->handle_refs);
+       InterlockedIncrement ((gint32 *)&shared->handle_refs);
        
 #ifdef DEBUG
-       g_message ("%s: Allocated new handle %p referencing 0x%x", __func__,
-                  handle, offset);
+       g_message ("%s: Allocated new handle %p referencing 0x%x (shared refs %d)", __func__, handle, offset, shared->handle_refs);
 #endif
        
 done:
@@ -460,6 +594,8 @@ gpointer _wapi_handle_new_fd (WapiHandleType type, int fd,
        struct _WapiHandleUnshared *handle;
        int thr_ret;
        
+       g_assert (_wapi_has_shut_down == FALSE);
+       
        mono_once (&shared_init_once, shared_init);
        
 #ifdef DEBUG
@@ -512,6 +648,10 @@ gboolean _wapi_lookup_handle (gpointer handle, WapiHandleType type,
        struct _WapiHandleUnshared *handle_data;
        guint32 handle_idx = GPOINTER_TO_UINT(handle);
 
+       if (!_WAPI_PRIVATE_VALID_SLOT (handle_idx)) {
+               return(FALSE);
+       }
+       
        handle_data = &_WAPI_PRIVATE_HANDLES(handle_idx);
        
        if (handle_data->type != type) {
@@ -585,7 +725,8 @@ _wapi_handle_foreach (WapiHandleType type,
 gpointer _wapi_search_handle (WapiHandleType type,
                              gboolean (*check)(gpointer test, gpointer user),
                              gpointer user_data,
-                             gpointer *handle_specific)
+                             gpointer *handle_specific,
+                             gboolean search_shared)
 {
        struct _WapiHandleUnshared *handle_data = NULL;
        struct _WapiHandleShared *shared;
@@ -606,7 +747,13 @@ gpointer _wapi_search_handle (WapiHandleType type,
                        if (handle_data->type == type) {
                                ret = GUINT_TO_POINTER (i * _WAPI_HANDLE_INITIAL_COUNT + k);
                                if (check (ret, user_data) == TRUE) {
+                                       _wapi_handle_ref (ret);
                                        found = TRUE;
+
+                                       if (_WAPI_SHARED_HANDLE (type)) {
+                                               shared = &_wapi_shared_layout->handles[i];
+                                       }
+                                       
                                        break;
                                }
                        }
@@ -617,7 +764,7 @@ gpointer _wapi_search_handle (WapiHandleType type,
        g_assert (thr_ret == 0);
        pthread_cleanup_pop (0);
 
-       if (!found && _WAPI_SHARED_HANDLE (type)) {
+       if (!found && search_shared && _WAPI_SHARED_HANDLE (type)) {
                /* Not found yet, so search the shared memory too */
 #ifdef DEBUG
                g_message ("%s: Looking at other shared handles...", __func__);
@@ -664,7 +811,7 @@ gpointer _wapi_search_handle (WapiHandleType type,
                                        
                                        if (shared->type == type) {
                                                guint32 now = (guint32)(time (NULL) & 0xFFFFFFFF);
-                                               InterlockedExchange (&shared->timestamp, now);
+                                               InterlockedExchange ((gint32 *)&shared->timestamp, now);
 
                                                found = TRUE;
                                                handle_data = &_WAPI_PRIVATE_HANDLES(GPOINTER_TO_UINT(ret));
@@ -740,8 +887,8 @@ gint32 _wapi_search_handle_namespace (WapiHandleType type,
                shared_handle_data = &_wapi_shared_layout->handles[i];
 
                /* Check mutex, event, semaphore, timer, job and
-                * file-mapping object names.  So far only mutex and
-                * semaphore are implemented.
+                * file-mapping object names.  So far only mutex,
+                * semaphore and event are implemented.
                 */
                if (!_WAPI_SHARED_NAMESPACE (shared_handle_data->type)) {
                        continue;
@@ -785,15 +932,21 @@ void _wapi_handle_ref (gpointer handle)
 {
        guint32 idx = GPOINTER_TO_UINT(handle);
        guint32 now = (guint32)(time (NULL) & 0xFFFFFFFF);
-       struct _WapiHandleUnshared *handle_data = &_WAPI_PRIVATE_HANDLES(idx);
+       struct _WapiHandleUnshared *handle_data;
 
+       if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
+               return;
+       }
+       
        if (_wapi_handle_type (handle) == WAPI_HANDLE_UNUSED) {
                g_warning ("%s: Attempting to ref unused handle %p", __func__,
                           handle);
                return;
        }
+
+       handle_data = &_WAPI_PRIVATE_HANDLES(idx);
        
-       InterlockedIncrement (&handle_data->ref);
+       InterlockedIncrement ((gint32 *)&handle_data->ref);
 
        /* It's possible for processes to exit before getting around
         * to updating timestamps in the collection thread, so if a
@@ -803,11 +956,13 @@ void _wapi_handle_ref (gpointer handle)
        if (_WAPI_SHARED_HANDLE(handle_data->type)) {
                struct _WapiHandleShared *shared_data = &_wapi_shared_layout->handles[handle_data->u.shared.offset];
                
-               InterlockedExchange (&shared_data->timestamp, now);
+               InterlockedExchange ((gint32 *)&shared_data->timestamp, now);
        }
        
 #ifdef DEBUG_REFS
-       g_message ("%s: handle %p ref now %d", __func__, handle,
+       g_message ("%s: %s handle %p ref now %d", __func__, 
+                  _wapi_handle_typename[_WAPI_PRIVATE_HANDLES (idx).type],
+                  handle,
                   _WAPI_PRIVATE_HANDLES(idx).ref);
 #endif
 }
@@ -819,6 +974,10 @@ void _wapi_handle_unref (gpointer handle)
        gboolean destroy = FALSE;
        int thr_ret;
 
+       if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
+               return;
+       }
+       
        if (_wapi_handle_type (handle) == WAPI_HANDLE_UNUSED) {
                g_warning ("%s: Attempting to unref unused handle %p",
                           __func__, handle);
@@ -830,10 +989,12 @@ void _wapi_handle_unref (gpointer handle)
         * could lock a mutex, but I'm not sure that allowing a handle
         * reference to reach 0 isn't an application bug anyway.
         */
-       destroy = (InterlockedDecrement (&_WAPI_PRIVATE_HANDLES(idx).ref) ==0);
+       destroy = (InterlockedDecrement ((gint32 *)&_WAPI_PRIVATE_HANDLES(idx).ref) ==0);
        
 #ifdef DEBUG_REFS
-       g_message ("%s: handle %p ref now %d (destroy %s)", __func__, handle,
+       g_message ("%s: %s handle %p ref now %d (destroy %s)", __func__,
+                  _wapi_handle_typename[_WAPI_PRIVATE_HANDLES (idx).type],
+                  handle,
                   _WAPI_PRIVATE_HANDLES(idx).ref, destroy?"TRUE":"FALSE");
 #endif
        
@@ -894,6 +1055,10 @@ void _wapi_handle_unref (gpointer handle)
                        /* It's possible that this handle is already
                         * pointing at a deleted shared section
                         */
+#ifdef DEBUG_REFS
+                       g_message ("%s: %s handle %p shared refs before dec %d", __func__, _wapi_handle_typename[type], handle, shared->handle_refs);
+#endif
+
                        if (shared->handle_refs > 0) {
                                shared->handle_refs--;
                                if (shared->handle_refs == 0) {
@@ -932,6 +1097,10 @@ gboolean _wapi_handle_test_capabilities (gpointer handle,
        guint32 idx = GPOINTER_TO_UINT(handle);
        WapiHandleType type;
 
+       if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
+               return(FALSE);
+       }
+       
        type = _WAPI_PRIVATE_HANDLES(idx).type;
 
 #ifdef DEBUG
@@ -957,6 +1126,10 @@ void _wapi_handle_ops_close (gpointer handle, gpointer data)
        guint32 idx = GPOINTER_TO_UINT(handle);
        WapiHandleType type;
 
+       if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
+               return;
+       }
+       
        type = _WAPI_PRIVATE_HANDLES(idx).type;
 
        if (handle_ops[type] != NULL &&
@@ -970,6 +1143,10 @@ void _wapi_handle_ops_signal (gpointer handle)
        guint32 idx = GPOINTER_TO_UINT(handle);
        WapiHandleType type;
 
+       if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
+               return;
+       }
+       
        type = _WAPI_PRIVATE_HANDLES(idx).type;
 
        if (handle_ops[type] != NULL && handle_ops[type]->signal != NULL) {
@@ -982,6 +1159,10 @@ gboolean _wapi_handle_ops_own (gpointer handle)
        guint32 idx = GPOINTER_TO_UINT(handle);
        WapiHandleType type;
        
+       if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
+               return(FALSE);
+       }
+       
        type = _WAPI_PRIVATE_HANDLES(idx).type;
 
        if (handle_ops[type] != NULL && handle_ops[type]->own_handle != NULL) {
@@ -996,6 +1177,10 @@ gboolean _wapi_handle_ops_isowned (gpointer handle)
        guint32 idx = GPOINTER_TO_UINT(handle);
        WapiHandleType type;
 
+       if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
+               return(FALSE);
+       }
+       
        type = _WAPI_PRIVATE_HANDLES(idx).type;
 
        if (handle_ops[type] != NULL && handle_ops[type]->is_owned != NULL) {
@@ -1010,6 +1195,10 @@ guint32 _wapi_handle_ops_special_wait (gpointer handle, guint32 timeout)
        guint32 idx = GPOINTER_TO_UINT(handle);
        WapiHandleType type;
        
+       if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
+               return(WAIT_FAILED);
+       }
+       
        type = _WAPI_PRIVATE_HANDLES(idx).type;
        
        if (handle_ops[type] != NULL &&
@@ -1020,6 +1209,23 @@ guint32 _wapi_handle_ops_special_wait (gpointer handle, guint32 timeout)
        }
 }
 
+void _wapi_handle_ops_prewait (gpointer handle)
+{
+       guint32 idx = GPOINTER_TO_UINT (handle);
+       WapiHandleType type;
+       
+       if (!_WAPI_PRIVATE_VALID_SLOT (idx)) {
+               return;
+       }
+       
+       type = _WAPI_PRIVATE_HANDLES (idx).type;
+       
+       if (handle_ops[type] != NULL &&
+           handle_ops[type]->prewait != NULL) {
+               handle_ops[type]->prewait (handle);
+       }
+}
+
 
 /**
  * CloseHandle:
@@ -1034,11 +1240,52 @@ guint32 _wapi_handle_ops_special_wait (gpointer handle, guint32 timeout)
  */
 gboolean CloseHandle(gpointer handle)
 {
+       if (handle == NULL) {
+               /* Problem: because we map file descriptors to the
+                * same-numbered handle we can't tell the difference
+                * between a bogus handle and the handle to stdin.
+                * Assume that it's the console handle if that handle
+                * exists...
+                */
+               if (_WAPI_PRIVATE_HANDLES (0).type != WAPI_HANDLE_CONSOLE) {
+                       SetLastError (ERROR_INVALID_PARAMETER);
+                       return(FALSE);
+               }
+       }
+       if (handle == _WAPI_HANDLE_INVALID){
+               SetLastError (ERROR_INVALID_PARAMETER);
+               return(FALSE);
+       }
+       
        _wapi_handle_unref (handle);
        
        return(TRUE);
 }
 
+/* Lots more to implement here, but this is all we need at the moment */
+gboolean DuplicateHandle (gpointer srcprocess, gpointer src,
+                         gpointer targetprocess, gpointer *target,
+                         guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, guint32 options G_GNUC_UNUSED)
+{
+       if (srcprocess != _WAPI_PROCESS_CURRENT ||
+           targetprocess != _WAPI_PROCESS_CURRENT) {
+               /* Duplicating other process's handles is not supported */
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+       
+       if (src == _WAPI_PROCESS_CURRENT) {
+               *target = _wapi_process_duplicate ();
+       } else if (src == _WAPI_THREAD_CURRENT) {
+               *target = _wapi_thread_duplicate ();
+       } else {
+               _wapi_handle_ref (src);
+               *target = src;
+       }
+       
+       return(TRUE);
+}
+
 gboolean _wapi_handle_count_signalled_handles (guint32 numhandles,
                                               gpointer *handles,
                                               gboolean waitall,
@@ -1184,26 +1431,33 @@ void _wapi_handle_unlock_handles (guint32 numhandles, gpointer *handles)
        }
 }
 
-static int timedwait_signal_poll_cond (pthread_cond_t *cond, mono_mutex_t *mutex, struct timespec *timeout)
+static int timedwait_signal_poll_cond (pthread_cond_t *cond, mono_mutex_t *mutex, struct timespec *timeout, gboolean alertable)
 {
        struct timespec fake_timeout;
        int ret;
-       
-       _wapi_calc_timeout (&fake_timeout, 100);
-       
-       if (timeout != NULL && ((fake_timeout.tv_sec > timeout->tv_sec) ||
-          (fake_timeout.tv_sec == timeout->tv_sec &&
-               fake_timeout.tv_nsec > timeout->tv_nsec))) {
-               /* Real timeout is less than 100ms time */
-               ret=mono_cond_timedwait (cond, mutex, timeout);
+
+       if (!alertable) {
+               if (timeout)
+                       ret=mono_cond_timedwait (cond, mutex, timeout);
+               else
+                       ret=mono_cond_wait (cond, mutex);
        } else {
-               ret=mono_cond_timedwait (cond, mutex, &fake_timeout);
+               _wapi_calc_timeout (&fake_timeout, 100);
+       
+               if (timeout != NULL && ((fake_timeout.tv_sec > timeout->tv_sec) ||
+                                                               (fake_timeout.tv_sec == timeout->tv_sec &&
+                                                                fake_timeout.tv_nsec > timeout->tv_nsec))) {
+                       /* Real timeout is less than 100ms time */
+                       ret=mono_cond_timedwait (cond, mutex, timeout);
+               } else {
+                       ret=mono_cond_timedwait (cond, mutex, &fake_timeout);
 
-               /* Mask the fake timeout, this will cause
-                * another poll if the cond was not really signaled
-                */
-               if (ret==ETIMEDOUT) {
-                       ret=0;
+                       /* Mask the fake timeout, this will cause
+                        * another poll if the cond was not really signaled
+                        */
+                       if (ret==ETIMEDOUT) {
+                               ret=0;
+                       }
                }
        }
        
@@ -1212,25 +1466,25 @@ static int timedwait_signal_poll_cond (pthread_cond_t *cond, mono_mutex_t *mutex
 
 int _wapi_handle_wait_signal (void)
 {
-       return timedwait_signal_poll_cond (&_wapi_global_signal_cond, &_wapi_global_signal_mutex, NULL);
+       return timedwait_signal_poll_cond (&_wapi_global_signal_cond, &_wapi_global_signal_mutex, NULL, TRUE);
 }
 
 int _wapi_handle_timedwait_signal (struct timespec *timeout)
 {
-       return timedwait_signal_poll_cond (&_wapi_global_signal_cond, &_wapi_global_signal_mutex, timeout);
+       return timedwait_signal_poll_cond (&_wapi_global_signal_cond, &_wapi_global_signal_mutex, timeout, TRUE);
 }
 
-int _wapi_handle_wait_signal_handle (gpointer handle)
+int _wapi_handle_wait_signal_handle (gpointer handle, gboolean alertable)
 {
 #ifdef DEBUG
        g_message ("%s: waiting for %p", __func__, handle);
 #endif
        
-       return _wapi_handle_timedwait_signal_handle (handle, NULL);
+       return _wapi_handle_timedwait_signal_handle (handle, NULL, alertable);
 }
 
 int _wapi_handle_timedwait_signal_handle (gpointer handle,
-                                         struct timespec *timeout)
+                                         struct timespec *timeout, gboolean alertable)
 {
 #ifdef DEBUG
        g_message ("%s: waiting for %p (type %s)", __func__, handle,
@@ -1266,7 +1520,7 @@ int _wapi_handle_timedwait_signal_handle (gpointer handle,
                
        } else {
                guint32 idx = GPOINTER_TO_UINT(handle);
-               return timedwait_signal_poll_cond (&_WAPI_PRIVATE_HANDLES(idx).signal_cond, &_WAPI_PRIVATE_HANDLES(idx).signal_mutex, timeout);
+               return timedwait_signal_poll_cond (&_WAPI_PRIVATE_HANDLES(idx).signal_cond, &_WAPI_PRIVATE_HANDLES(idx).signal_mutex, timeout, alertable);
        }
 }
 
@@ -1281,7 +1535,7 @@ gboolean _wapi_handle_get_or_set_share (dev_t device, ino_t inode,
        guint32 now = (guint32)(time(NULL) & 0xFFFFFFFF);
        int thr_ret, i, first_unused = -1;
        gboolean exists = FALSE;
-       
+
        /* Prevents entries from expiring under us as we search
         */
        thr_ret = _wapi_handle_lock_shared_handles ();
@@ -1321,7 +1575,7 @@ gboolean _wapi_handle_get_or_set_share (dev_t device, ino_t inode,
                         * This makes the increment atomic wrt
                         * collections
                         */
-                       InterlockedIncrement (&file_share->handle_refs);
+                       InterlockedIncrement ((gint32 *)&file_share->handle_refs);
                        
                        exists = TRUE;
                        break;
@@ -1341,7 +1595,7 @@ gboolean _wapi_handle_get_or_set_share (dev_t device, ino_t inode,
                        
                        file_share->device = device;
                        file_share->inode = inode;
-                       file_share->opened_by_pid = getpid ();
+                       file_share->opened_by_pid = _wapi_getpid ();
                        file_share->sharemode = new_sharemode;
                        file_share->access = new_access;
                        file_share->handle_refs = 1;
@@ -1350,7 +1604,7 @@ gboolean _wapi_handle_get_or_set_share (dev_t device, ino_t inode,
        }
 
        if (*share_info != NULL) {
-               InterlockedExchange (&(*share_info)->timestamp, now);
+               InterlockedExchange ((gint32 *)&(*share_info)->timestamp, now);
        }
        
        thr_ret = _wapi_shm_sem_unlock (_WAPI_SHARED_SEM_FILESHARE);
@@ -1391,7 +1645,7 @@ static void _wapi_handle_check_share_by_pid (struct _WapiFileShare *share_info)
 void _wapi_handle_check_share (struct _WapiFileShare *share_info, int fd)
 {
        gboolean found = FALSE, proc_fds = FALSE;
-       pid_t self = getpid();
+       pid_t self = _wapi_getpid ();
        int pid;
        int thr_ret, i;
        
@@ -1579,37 +1833,30 @@ void _wapi_handle_update_refs (void)
                                struct _WapiHandleShared *shared_data;
                                
 #ifdef DEBUG
-                               g_message ("%s: (%d) handle 0x%x is SHARED (%s)", __func__,
-                                          getpid (), i * _WAPI_HANDLE_INITIAL_COUNT + k, _wapi_handle_typename[handle->type]);
+                               g_message ("%s: (%d) handle 0x%x is SHARED (%s)", __func__, _wapi_getpid (), i * _WAPI_HANDLE_INITIAL_COUNT + k, _wapi_handle_typename[handle->type]);
 #endif
 
                                shared_data = &_wapi_shared_layout->handles[handle->u.shared.offset];
 
 #ifdef DEBUG
-                               g_message ("%s: (%d) Updating timestamp of handle 0x%x",
-                                          __func__, getpid(),
-                                          handle->u.shared.offset);
+                               g_message ("%s: (%d) Updating timestamp of handle 0x%x", __func__, _wapi_getpid (), handle->u.shared.offset);
 #endif
 
-                               InterlockedExchange (&shared_data->timestamp,
-                                                    now);
+                               InterlockedExchange ((gint32 *)&shared_data->timestamp, now);
                        } else if (handle->type == WAPI_HANDLE_FILE) {
                                struct _WapiHandle_file *file_handle = &handle->u.file;
                                
 #ifdef DEBUG
-                               g_message ("%s: (%d) handle 0x%x is FILE", __func__,
-                                          getpid (), i * _WAPI_HANDLE_INITIAL_COUNT + k);
+                               g_message ("%s: (%d) handle 0x%x is FILE", __func__, _wapi_getpid (), i * _WAPI_HANDLE_INITIAL_COUNT + k);
 #endif
                                
                                g_assert (file_handle->share_info != NULL);
 
 #ifdef DEBUG
-                               g_message ("%s: (%d) Inc refs on fileshare 0x%x",
-                                          __func__, getpid(),
-                                          (file_handle->share_info - &_wapi_fileshare_layout->share_info[0]) / sizeof(struct _WapiFileShare));
+                               g_message ("%s: (%d) Inc refs on fileshare 0x%x", __func__, _wapi_getpid (), (file_handle->share_info - &_wapi_fileshare_layout->share_info[0]) / sizeof(struct _WapiFileShare));
 #endif
 
-                               InterlockedExchange (&file_handle->share_info->timestamp, now);
+                               InterlockedExchange ((gint32 *)&file_handle->share_info->timestamp, now);
                        }
                }
        }
@@ -1622,3 +1869,4 @@ void _wapi_handle_update_refs (void)
 
        _wapi_handle_unlock_shared_handles ();
 }
+