2007-09-02 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / io-layer / handles.c
index c78b7ca2fbe41645ae526e58610404e524c40af9..7e9c173ceaab42ed5a51c0f0f6a05ac85cdbb365 100644 (file)
@@ -30,6 +30,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
@@ -110,6 +111,7 @@ 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
@@ -184,6 +186,20 @@ static void handle_cleanup (void)
        }
        
        _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;
@@ -232,6 +248,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 +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;
@@ -272,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 */
@@ -327,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
@@ -372,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
@@ -453,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
@@ -566,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
@@ -1210,6 +1240,23 @@ void _wapi_handle_ops_prewait (gpointer handle)
  */
 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);
@@ -1384,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;
+                       }
                }
        }
        
@@ -1412,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,
@@ -1466,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);
        }
 }