Flush (work in progress)
[mono.git] / mono / io-layer / handles.c
index f9de22c044a3c17f77de957d275a095f0b8bb6b8..d103db010bf18bcc306d8998847a2190c3373b67 100644 (file)
 #include <unistd.h>
 #include <string.h>
 #include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/mman.h>
-#include <dirent.h>
+#ifdef HAVE_SYS_SOCKET_H
+#  include <sys/socket.h>
+#endif
+#ifdef HAVE_SYS_UN_H
+#  include <sys/un.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+#  include <sys/mman.h>
+#endif
+#ifdef HAVE_DIRENT_H
+#  include <dirent.h>
+#endif
 #include <sys/stat.h>
 
-#include <mono/os/gc_wrapper.h>
+#include <mono/utils/gc_wrapper.h>
 
 #include <mono/io-layer/wapi.h>
 #include <mono/io-layer/wapi-private.h>
@@ -30,6 +38,7 @@
 #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
@@ -45,7 +54,9 @@ static struct _WapiHandleOps *handle_ops[WAPI_HANDLE_COUNT]={
        &_wapi_sem_ops,
        &_wapi_mutex_ops,
        &_wapi_event_ops,
+#ifndef DISABLE_SOCKETS
        &_wapi_socket_ops,
+#endif
        &_wapi_find_ops,
        &_wapi_process_ops,
        &_wapi_pipe_ops,
@@ -100,16 +111,26 @@ const char *_wapi_handle_typename[] = {
 
 struct _WapiHandleUnshared *_wapi_private_handles [_WAPI_PRIVATE_MAX_SLOTS];
 static guint32 _wapi_private_handle_count = 0;
+static guint32 _wapi_private_handle_slot_count = 0;
 
 struct _WapiHandleSharedLayout *_wapi_shared_layout = NULL;
 struct _WapiFileShareLayout *_wapi_fileshare_layout = NULL;
 
 guint32 _wapi_fd_reserve;
 
-mono_mutex_t _wapi_global_signal_mutex;
-pthread_cond_t _wapi_global_signal_cond;
+/* 
+ * This is an internal handle which is used for handling waiting for multiple handles.
+ * Threads which wait for multiple handles wait on this one handle, and when a handle
+ * is signalled, this handle is signalled too.
+ */
+static gpointer _wapi_global_signal_handle;
+
+/* Point to the mutex/cond inside _wapi_global_signal_handle */
+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
@@ -118,6 +139,8 @@ int _wapi_sem_id;
 static pid_t _wapi_pid;
 static mono_once_t pid_init_once = MONO_ONCE_INIT;
 
+static gpointer _wapi_handle_real_new (WapiHandleType type, gpointer handle_specific);
+
 static void pid_init (void)
 {
        _wapi_pid = getpid ();
@@ -186,22 +209,40 @@ static void handle_cleanup (void)
        _wapi_shm_semaphores_remove ();
 }
 
+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)
 {
-       int thr_ret;
-       int idx = 0;
-       
        g_assert ((sizeof (handle_ops) / sizeof (handle_ops[0]))
                  == WAPI_HANDLE_COUNT);
        
        _wapi_fd_reserve = getdtablesize();
 
+       /* This is needed by the code in _wapi_handle_new_internal */
+       _wapi_fd_reserve = (_wapi_fd_reserve + (_WAPI_HANDLE_INITIAL_COUNT - 1)) & ~(_WAPI_HANDLE_INITIAL_COUNT - 1);
+
        do {
+               /* 
+                * The entries in _wapi_private_handles reserved for fds are allocated lazily to 
+                * save memory.
+                */
+               /*
                _wapi_private_handles [idx++] = g_new0 (struct _WapiHandleUnshared,
                                                        _WAPI_HANDLE_INITIAL_COUNT);
+               */
 
                _wapi_private_handle_count += _WAPI_HANDLE_INITIAL_COUNT;
+               _wapi_private_handle_slot_count ++;
        } while(_wapi_fd_reserve > _wapi_private_handle_count);
 
        _wapi_shm_semaphores_init ();
@@ -212,13 +253,16 @@ static void shared_init (void)
        _wapi_fileshare_layout = _wapi_shm_attach (WAPI_SHM_FILESHARE);
        g_assert (_wapi_fileshare_layout != NULL);
        
-       _wapi_collection_init ();
-       
-       thr_ret = pthread_cond_init(&_wapi_global_signal_cond, NULL);
-       g_assert (thr_ret == 0);
-       
-       thr_ret = mono_mutex_init(&_wapi_global_signal_mutex, NULL);
-       g_assert (thr_ret == 0);
+#if !defined (DISABLE_SHARED_HANDLES)
+       if (!g_getenv ("MONO_DISABLE_SHM"))
+               _wapi_collection_init ();
+#endif
+
+       /* Can't call wapi_handle_new as it calls us recursively */
+       _wapi_global_signal_handle = _wapi_handle_real_new (WAPI_HANDLE_EVENT, NULL);
+
+       _wapi_global_signal_cond = &_WAPI_PRIVATE_HANDLES (GPOINTER_TO_UINT (_wapi_global_signal_handle)).signal_cond;
+       _wapi_global_signal_mutex = &_WAPI_PRIVATE_HANDLES (GPOINTER_TO_UINT (_wapi_global_signal_handle)).signal_mutex;
 
        /* Using g_atexit here instead of an explicit function call in
         * a cleanup routine lets us cope when a third-party library
@@ -232,6 +276,8 @@ 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;
@@ -247,6 +293,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;
@@ -272,6 +320,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 */
@@ -327,6 +377,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
@@ -341,17 +393,19 @@ static guint32 _wapi_handle_new_internal (WapiHandleType type,
 
 again:
        count = last;
-       for(i = SLOT_INDEX (count); _wapi_private_handles [i] != NULL; i++) {
-               for (k = SLOT_OFFSET (count); k < _WAPI_HANDLE_INITIAL_COUNT; k++) {
-                       struct _WapiHandleUnshared *handle = &_wapi_private_handles [i][k];
+       for(i = SLOT_INDEX (count); i < _wapi_private_handle_slot_count; i++) {
+               if (_wapi_private_handles [i]) {
+                       for (k = SLOT_OFFSET (count); k < _WAPI_HANDLE_INITIAL_COUNT; k++) {
+                               struct _WapiHandleUnshared *handle = &_wapi_private_handles [i][k];
 
-                       if(handle->type == WAPI_HANDLE_UNUSED) {
-                               last = count + 1;
+                               if(handle->type == WAPI_HANDLE_UNUSED) {
+                                       last = count + 1;
                        
-                               _wapi_handle_init (handle, type, handle_specific);
-                               return (count);
+                                       _wapi_handle_init (handle, type, handle_specific);
+                                       return (count);
+                               }
+                               count++;
                        }
-                       count++;
                }
        }
 
@@ -366,14 +420,12 @@ again:
        return(0);
 }
 
-gpointer _wapi_handle_new (WapiHandleType type, gpointer handle_specific)
+static gpointer _wapi_handle_real_new (WapiHandleType type, gpointer handle_specific)
 {
        guint32 handle_idx = 0;
        gpointer handle;
        int thr_ret;
        
-       mono_once (&shared_init_once, shared_init);
-       
 #ifdef DEBUG
        g_message ("%s: Creating new handle of type %s", __func__,
                   _wapi_handle_typename[type]);
@@ -392,11 +444,12 @@ gpointer _wapi_handle_new (WapiHandleType type, gpointer handle_specific)
                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;
+               _wapi_private_handle_slot_count ++;
        }
        
        thr_ret = mono_mutex_unlock (&scan_mutex);
@@ -425,6 +478,7 @@ gpointer _wapi_handle_new (WapiHandleType type, gpointer handle_specific)
                ref = _wapi_handle_new_shared (type, handle_specific);
                if (ref == 0) {
                        _wapi_handle_collect ();
+                       _wapi_process_reap ();
                        ref = _wapi_handle_new_shared (type, handle_specific);
                        if (ref == 0) {
                                /* FIXME: grow the arrays */
@@ -444,6 +498,15 @@ done:
        return(handle);
 }
 
+gpointer _wapi_handle_new (WapiHandleType type, gpointer handle_specific)
+{
+       g_assert (_wapi_has_shut_down == FALSE);
+       
+       mono_once (&shared_init_once, shared_init);
+
+       return _wapi_handle_real_new (type, handle_specific);
+}
+
 gpointer _wapi_handle_new_from_offset (WapiHandleType type, guint32 offset,
                                       gboolean timestamp)
 {
@@ -453,6 +516,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
@@ -475,14 +540,16 @@ gpointer _wapi_handle_new_from_offset (WapiHandleType type, guint32 offset,
        thr_ret = mono_mutex_lock (&scan_mutex);
        g_assert (thr_ret == 0);
 
-       for (i = SLOT_INDEX (0); _wapi_private_handles [i] != NULL; i++) {
-               for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) {
-                       struct _WapiHandleUnshared *handle_data = &_wapi_private_handles [i][k];
+       for (i = SLOT_INDEX (0); i < _wapi_private_handle_slot_count; i++) {
+               if (_wapi_private_handles [i]) {
+                       for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) {
+                               struct _WapiHandleUnshared *handle_data = &_wapi_private_handles [i][k];
                
-                       if (handle_data->type == type &&
-                           handle_data->u.shared.offset == offset) {
-                               handle = GUINT_TO_POINTER (i * _WAPI_HANDLE_INITIAL_COUNT + k);
-                               goto first_pass_done;
+                               if (handle_data->type == type &&
+                                       handle_data->u.shared.offset == offset) {
+                                       handle = GUINT_TO_POINTER (i * _WAPI_HANDLE_INITIAL_COUNT + k);
+                                       goto first_pass_done;
+                               }
                        }
                }
        }
@@ -536,6 +603,7 @@ first_pass_done:
                                                _WAPI_HANDLE_INITIAL_COUNT);
 
                _wapi_private_handle_count += _WAPI_HANDLE_INITIAL_COUNT;
+               _wapi_private_handle_slot_count ++;
        }
                
        thr_ret = mono_mutex_unlock (&scan_mutex);
@@ -560,12 +628,35 @@ done:
        return(handle);
 }
 
+static void
+init_handles_slot (int idx)
+{
+       int thr_ret;
+
+       pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
+                                                 (void *)&scan_mutex);
+       thr_ret = mono_mutex_lock (&scan_mutex);
+       g_assert (thr_ret == 0);
+
+       if (_wapi_private_handles [idx] == NULL) {
+               _wapi_private_handles [idx] = g_new0 (struct _WapiHandleUnshared,
+                                                                                         _WAPI_HANDLE_INITIAL_COUNT);
+               g_assert (_wapi_private_handles [idx]);
+       }
+
+       thr_ret = mono_mutex_unlock (&scan_mutex);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
+}
+
 gpointer _wapi_handle_new_fd (WapiHandleType type, int fd,
                              gpointer handle_specific)
 {
        struct _WapiHandleUnshared *handle;
        int thr_ret;
        
+       g_assert (_wapi_has_shut_down == FALSE);
+       
        mono_once (&shared_init_once, shared_init);
        
 #ifdef DEBUG
@@ -584,6 +675,10 @@ gpointer _wapi_handle_new_fd (WapiHandleType type, int fd,
                return(GUINT_TO_POINTER (_WAPI_HANDLE_INVALID));
        }
 
+       /* Initialize the array entries on demand */
+       if (_wapi_private_handles [SLOT_INDEX (fd)] == NULL)
+               init_handles_slot (SLOT_INDEX (fd));
+
        handle = &_WAPI_PRIVATE_HANDLES(fd);
        
        if (handle->type != WAPI_HANDLE_UNUSED) {
@@ -621,6 +716,10 @@ gboolean _wapi_lookup_handle (gpointer handle, WapiHandleType type,
        if (!_WAPI_PRIVATE_VALID_SLOT (handle_idx)) {
                return(FALSE);
        }
+
+       /* Initialize the array entries on demand */
+       if (_wapi_private_handles [SLOT_INDEX (handle_idx)] == NULL)
+               init_handles_slot (SLOT_INDEX (handle_idx));
        
        handle_data = &_WAPI_PRIVATE_HANDLES(handle_idx);
        
@@ -668,14 +767,16 @@ _wapi_handle_foreach (WapiHandleType type,
        thr_ret = mono_mutex_lock (&scan_mutex);
        g_assert (thr_ret == 0);
 
-       for (i = SLOT_INDEX (0); _wapi_private_handles [i] != NULL; i++) {
-               for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) {
-                       handle_data = &_wapi_private_handles [i][k];
-               
-                       if (handle_data->type == type) {
-                               ret = GUINT_TO_POINTER (i * _WAPI_HANDLE_INITIAL_COUNT + k);
-                               if (on_each (ret, user_data) == TRUE)
-                                       break;
+       for (i = SLOT_INDEX (0); i < _wapi_private_handle_slot_count; i++) {
+               if (_wapi_private_handles [i]) {
+                       for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) {
+                               handle_data = &_wapi_private_handles [i][k];
+                       
+                               if (handle_data->type == type) {
+                                       ret = GUINT_TO_POINTER (i * _WAPI_HANDLE_INITIAL_COUNT + k);
+                                       if (on_each (ret, user_data) == TRUE)
+                                               break;
+                               }
                        }
                }
        }
@@ -699,7 +800,7 @@ gpointer _wapi_search_handle (WapiHandleType type,
                              gboolean search_shared)
 {
        struct _WapiHandleUnshared *handle_data = NULL;
-       struct _WapiHandleShared *shared;
+       struct _WapiHandleShared *shared = NULL;
        gpointer ret = NULL;
        guint32 i, k;
        gboolean found = FALSE;
@@ -710,21 +811,23 @@ gpointer _wapi_search_handle (WapiHandleType type,
        thr_ret = mono_mutex_lock (&scan_mutex);
        g_assert (thr_ret == 0);
        
-       for (i = SLOT_INDEX (0); !found && _wapi_private_handles [i] != NULL; i++) {
-               for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) {
-                       handle_data = &_wapi_private_handles [i][k];
+       for (i = SLOT_INDEX (0); !found && i < _wapi_private_handle_slot_count; i++) {
+               if (_wapi_private_handles [i]) {
+                       for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) {
+                               handle_data = &_wapi_private_handles [i][k];
                
-                       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 (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];
-                                       }
+                                               if (_WAPI_SHARED_HANDLE (type)) {
+                                                       shared = &_wapi_shared_layout->handles[i];
+                                               }
                                        
-                                       break;
+                                               break;
+                                       }
                                }
                        }
                }
@@ -1337,8 +1440,6 @@ again:
                
                type = _WAPI_PRIVATE_HANDLES(idx).type;
 
-               _wapi_handle_ref (handle);
-               
 #ifdef DEBUG
                g_message ("%s: Checking handle %p", __func__, handle);
 #endif
@@ -1434,14 +1535,14 @@ static int timedwait_signal_poll_cond (pthread_cond_t *cond, mono_mutex_t *mutex
        return(ret);
 }
 
-int _wapi_handle_wait_signal (void)
+int _wapi_handle_wait_signal (gboolean poll)
 {
-       return timedwait_signal_poll_cond (&_wapi_global_signal_cond, &_wapi_global_signal_mutex, NULL, TRUE);
+       return _wapi_handle_timedwait_signal_handle (_wapi_global_signal_handle, NULL, TRUE, poll);
 }
 
-int _wapi_handle_timedwait_signal (struct timespec *timeout)
+int _wapi_handle_timedwait_signal (struct timespec *timeout, gboolean poll)
 {
-       return timedwait_signal_poll_cond (&_wapi_global_signal_cond, &_wapi_global_signal_mutex, timeout, TRUE);
+       return _wapi_handle_timedwait_signal_handle (_wapi_global_signal_handle, timeout, TRUE, poll);
 }
 
 int _wapi_handle_wait_signal_handle (gpointer handle, gboolean alertable)
@@ -1450,11 +1551,11 @@ int _wapi_handle_wait_signal_handle (gpointer handle, gboolean alertable)
        g_message ("%s: waiting for %p", __func__, handle);
 #endif
        
-       return _wapi_handle_timedwait_signal_handle (handle, NULL, alertable);
+       return _wapi_handle_timedwait_signal_handle (handle, NULL, alertable, FALSE);
 }
 
 int _wapi_handle_timedwait_signal_handle (gpointer handle,
-                                         struct timespec *timeout, gboolean alertable)
+                                                                                 struct timespec *timeout, gboolean alertable, gboolean poll)
 {
 #ifdef DEBUG
        g_message ("%s: waiting for %p (type %s)", __func__, handle,
@@ -1490,7 +1591,30 @@ 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, alertable);
+               int res;
+               pthread_cond_t *cond;
+               mono_mutex_t *mutex;
+
+               if (alertable && !wapi_thread_set_wait_handle (handle))
+                       return 0;
+
+               cond = &_WAPI_PRIVATE_HANDLES (idx).signal_cond;
+               mutex = &_WAPI_PRIVATE_HANDLES (idx).signal_mutex;
+
+               if (poll) {
+                       /* This is needed when waiting for process handles */
+                       res = timedwait_signal_poll_cond (cond, mutex, timeout, alertable);
+               } else {
+                       if (timeout)
+                               res = mono_cond_timedwait (cond, mutex, timeout);
+                       else
+                               res = mono_cond_wait (cond, mutex);
+               }
+
+               if (alertable)
+                       wapi_thread_clear_wait_handle (handle);
+
+               return res;
        }
 }
 
@@ -1605,6 +1729,7 @@ static void _wapi_handle_check_share_by_pid (struct _WapiFileShare *share_info)
        }
 }
 
+#ifdef __linux__
 /* Scan /proc/<pids>/fd/ for open file descriptors to the file in
  * question.  If there are none, reset the share info.
  *
@@ -1640,19 +1765,21 @@ void _wapi_handle_check_share (struct _WapiFileShare *share_info, int fd)
         * See bugs 75764 and 75891
         */
        for (i = 0; i < _wapi_fd_reserve; i++) {
-               struct _WapiHandleUnshared *handle = &_WAPI_PRIVATE_HANDLES(i);
+               if (_wapi_private_handles [SLOT_INDEX (i)]) {
+                       struct _WapiHandleUnshared *handle = &_WAPI_PRIVATE_HANDLES(i);
 
-               if (i != fd &&
-                   handle->type == WAPI_HANDLE_FILE) {
-                       struct _WapiHandle_file *file_handle = &handle->u.file;
+                       if (i != fd &&
+                               handle->type == WAPI_HANDLE_FILE) {
+                               struct _WapiHandle_file *file_handle = &handle->u.file;
 
-                       if (file_handle->share_info == share_info) {
+                               if (file_handle->share_info == share_info) {
 #ifdef DEBUG
-                               g_message ("%s: handle 0x%x has this file open!",
-                                          __func__, i);
+                                       g_message ("%s: handle 0x%x has this file open!",
+                                                          __func__, i);
 #endif
 
-                               goto done;
+                                       goto done;
+                               }
                        }
                }
        }
@@ -1736,6 +1863,29 @@ done:
 
        _wapi_handle_unlock_shared_handles ();
 }
+#else
+//
+// Other implementations (non-Linux)
+//
+void _wapi_handle_check_share (struct _WapiFileShare *share_info, int fd)
+{
+       int thr_ret;
+       
+       /* Prevents entries from expiring under us if we remove this
+        * one */
+       thr_ret = _wapi_handle_lock_shared_handles ();
+       g_assert (thr_ret == 0);
+       
+       /* Prevent new entries racing with us */
+       thr_ret = _wapi_shm_sem_lock (_WAPI_SHARED_SEM_FILESHARE);
+       g_assert (thr_ret == 0);
+       
+       _wapi_handle_check_share_by_pid (share_info);
+
+       thr_ret = _wapi_shm_sem_unlock (_WAPI_SHARED_SEM_FILESHARE);
+       _wapi_handle_unlock_shared_handles ();
+}
+#endif
 
 void _wapi_handle_dump (void)
 {
@@ -1748,21 +1898,23 @@ void _wapi_handle_dump (void)
        thr_ret = mono_mutex_lock (&scan_mutex);
        g_assert (thr_ret == 0);
        
-       for(i = SLOT_INDEX (0); _wapi_private_handles [i] != NULL; i++) {
-               for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) {
-                       handle_data = &_wapi_private_handles [i][k];
+       for(i = SLOT_INDEX (0); i < _wapi_private_handle_slot_count; i++) {
+               if (_wapi_private_handles [i]) {
+                       for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) {
+                               handle_data = &_wapi_private_handles [i][k];
 
-                       if (handle_data->type == WAPI_HANDLE_UNUSED) {
-                               continue;
-                       }
+                               if (handle_data->type == WAPI_HANDLE_UNUSED) {
+                                       continue;
+                               }
                
-                       g_print ("%3x [%7s] %s %d ",
-                                i * _WAPI_HANDLE_INITIAL_COUNT + k,
-                                _wapi_handle_typename[handle_data->type],
-                                handle_data->signalled?"Sg":"Un",
-                                handle_data->ref);
-                       handle_details[handle_data->type](&handle_data->u);
-                       g_print ("\n");
+                               g_print ("%3x [%7s] %s %d ",
+                                                i * _WAPI_HANDLE_INITIAL_COUNT + k,
+                                                _wapi_handle_typename[handle_data->type],
+                                                handle_data->signalled?"Sg":"Un",
+                                                handle_data->ref);
+                               handle_details[handle_data->type](&handle_data->u);
+                               g_print ("\n");
+                       }
                }
        }
 
@@ -1795,38 +1947,40 @@ void _wapi_handle_update_refs (void)
                              (void *)&scan_mutex);
        thr_ret = mono_mutex_lock (&scan_mutex);
        
-       for(i = SLOT_INDEX (0); _wapi_private_handles [i] != NULL; i++) {
-               for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) {
-                       struct _WapiHandleUnshared *handle = &_wapi_private_handles [i][k];
+       for(i = SLOT_INDEX (0); i < _wapi_private_handle_slot_count; i++) {
+               if (_wapi_private_handles [i]) {
+                       for (k = SLOT_OFFSET (0); k < _WAPI_HANDLE_INITIAL_COUNT; k++) {
+                               struct _WapiHandleUnshared *handle = &_wapi_private_handles [i][k];
 
-                       if (_WAPI_SHARED_HANDLE(handle->type)) {
-                               struct _WapiHandleShared *shared_data;
+                               if (_WAPI_SHARED_HANDLE(handle->type)) {
+                                       struct _WapiHandleShared *shared_data;
                                
 #ifdef DEBUG
-                               g_message ("%s: (%d) handle 0x%x is SHARED (%s)", __func__, _wapi_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];
+                                       shared_data = &_wapi_shared_layout->handles[handle->u.shared.offset];
 
 #ifdef DEBUG
-                               g_message ("%s: (%d) Updating timestamp of handle 0x%x", __func__, _wapi_getpid (), handle->u.shared.offset);
+                                       g_message ("%s: (%d) Updating timestamp of handle 0x%x", __func__, _wapi_getpid (), handle->u.shared.offset);
 #endif
 
-                               InterlockedExchange ((gint32 *)&shared_data->timestamp, now);
-                       } else if (handle->type == WAPI_HANDLE_FILE) {
-                               struct _WapiHandle_file *file_handle = &handle->u.file;
+                                       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__, _wapi_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);
+                                       g_assert (file_handle->share_info != NULL);
 
 #ifdef DEBUG
-                               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));
+                                       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 ((gint32 *)&file_handle->share_info->timestamp, now);
+                                       InterlockedExchange ((gint32 *)&file_handle->share_info->timestamp, now);
+                               }
                        }
                }
        }