2004-04-22 Dick Porter <dick@ximian.com>
authorDick Porter <dick@acm.org>
Thu, 22 Apr 2004 14:37:44 +0000 (14:37 -0000)
committerDick Porter <dick@acm.org>
Thu, 22 Apr 2004 14:37:44 +0000 (14:37 -0000)
* handles.c:
* handles-private.h: Reference the handle when it is locked, so
that another thread can't blow it away while we're waiting for it
to become signalled.

* wait.c:
* timed-thread.c:
* threads.c:
* sockets.c:
* semaphores.c:
* mutexes.c:
* mono-mutex.c:
* io.c:
* handles.c:
* handles-private.h:
* events.c:
* error.c:
* daemon-messages.c:
* critical-sections.c:
* atomic.c: Added pthreads cleanup handlers and error asserts

* shared.c:
* handles.c: Fixed the gcc "variable might be used uninitialised"
warnings.  They can't happen, but gcc doesn't know that
g_assert()s don't return.

Fixed the declaration of _wapi_handle_process_kill() so that it
expects the correct type for the pid.

* threads.c: Removed the TLS_PTHREAD_MUTEX style locking that
hasn't been used in ages and just made the code more complex.

svn path=/trunk/mono/; revision=25834

19 files changed:
mono/io-layer/ChangeLog
mono/io-layer/atomic.c
mono/io-layer/critical-sections.c
mono/io-layer/daemon-messages.c
mono/io-layer/error.c
mono/io-layer/events.c
mono/io-layer/handles-private.h
mono/io-layer/handles.c
mono/io-layer/io.c
mono/io-layer/mono-mutex.c
mono/io-layer/mono-mutex.h
mono/io-layer/mutexes.c
mono/io-layer/semaphores.c
mono/io-layer/shared.c
mono/io-layer/sockets.c
mono/io-layer/thread-private.h
mono/io-layer/threads.c
mono/io-layer/timed-thread.c
mono/io-layer/wait.c

index 6f95327769747a0b5c51d35b7f497da6653c1025..29872b75d3bd5dbe98cea18c05cef3390107bbc3 100644 (file)
@@ -1,3 +1,37 @@
+2004-04-22  Dick Porter  <dick@ximian.com>
+
+       * handles.c: 
+       * handles-private.h: Reference the handle when it is locked, so
+       that another thread can't blow it away while we're waiting for it
+       to become signalled.
+       
+       * wait.c: 
+       * timed-thread.c: 
+       * threads.c: 
+       * sockets.c: 
+       * semaphores.c: 
+       * mutexes.c: 
+       * mono-mutex.c: 
+       * io.c: 
+       * handles.c: 
+       * handles-private.h: 
+       * events.c: 
+       * error.c: 
+       * daemon-messages.c: 
+       * critical-sections.c: 
+       * atomic.c: Added pthreads cleanup handlers and error asserts
+
+       * shared.c: 
+       * handles.c: Fixed the gcc "variable might be used uninitialised"
+       warnings.  They can't happen, but gcc doesn't know that
+       g_assert()s don't return.
+
+       Fixed the declaration of _wapi_handle_process_kill() so that it
+       expects the correct type for the pid.
+       
+       * threads.c: Removed the TLS_PTHREAD_MUTEX style locking that
+       hasn't been used in ages and just made the code more complex.
+
 2004-04-17  Zoltan Varga  <vargaz@freemail.hu>
 
        * processes.c: Include <signal.h> for SIGKILL and SIGILL + fix some
index 7e8998c87c6ae17b15aca2ed3718e04f8841a22b..67a4e63efa6a9a1b74a6c5ed36ce93fd96734c4d 100644 (file)
@@ -20,12 +20,11 @@ volatile unsigned char _wapi_sparc_lock;
 #endif
 #else
 
-static pthread_mutex_t spin;
+static pthread_mutex_t spin = PTHREAD_MUTEX_INITIALIZER;
 static mono_once_t spin_once=MONO_ONCE_INIT;
 
 static void spin_init(void)
 {
-       pthread_mutex_init(&spin, 0);
        g_warning("Using non-atomic functions!");
 }
 
@@ -33,16 +32,24 @@ gint32 InterlockedCompareExchange(volatile gint32 *dest, gint32 exch,
                                  gint32 comp)
 {
        gint32 old;
+       int ret;
        
        mono_once(&spin_once, spin_init);
-       pthread_mutex_lock(&spin);
+       
+       pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+                             (void *)&spin);
+       ret = pthread_mutex_lock(&spin);
+       g_assert (ret == 0);
        
        old= *dest;
        if(old==comp) {
                *dest=exch;
        }
        
-       pthread_mutex_unlock(&spin);
+       ret = pthread_mutex_unlock(&spin);
+       g_assert (ret == 0);
+       
+       pthread_cleanup_pop (0);
 
        return(old);
 }
@@ -51,16 +58,24 @@ gpointer InterlockedCompareExchangePointer(volatile gpointer *dest,
                                           gpointer exch, gpointer comp)
 {
        gpointer old;
+       int ret;
        
        mono_once(&spin_once, spin_init);
-       pthread_mutex_lock(&spin);
+       
+       pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+                             (void *)&spin);
+       ret = pthread_mutex_lock(&spin);
+       g_assert (ret == 0);
        
        old= *dest;
        if(old==comp) {
                *dest=exch;
        }
        
-       pthread_mutex_unlock(&spin);
+       ret = pthread_mutex_unlock(&spin);
+       g_assert (ret == 0);
+       
+       pthread_cleanup_pop (0);
 
        return(old);
 }
@@ -68,14 +83,22 @@ gpointer InterlockedCompareExchangePointer(volatile gpointer *dest,
 gint32 InterlockedIncrement(volatile gint32 *dest)
 {
        gint32 ret;
+       int thr_ret;
        
        mono_once(&spin_once, spin_init);
-       pthread_mutex_lock(&spin);
+       
+       pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+                             (void *)&spin);
+       thr_ret = pthread_mutex_lock(&spin);
+       g_assert (thr_ret == 0);
        
        *dest++;
        ret= *dest;
        
-       pthread_mutex_unlock(&spin);
+       thr_ret = pthread_mutex_unlock(&spin);
+       g_assert (thr_ret == 0);
+       
+       pthread_cleanup_pop (0);
        
        return(ret);
 }
@@ -83,14 +106,22 @@ gint32 InterlockedIncrement(volatile gint32 *dest)
 gint32 InterlockedDecrement(volatile gint32 *dest)
 {
        gint32 ret;
+       int thr_ret;
        
        mono_once(&spin_once, spin_init);
-       pthread_mutex_lock(&spin);
+       
+       pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+                             (void *)&spin);
+       thr_ret = pthread_mutex_lock(&spin);
+       g_assert (thr_ret == 0);
        
        *dest--;
        ret= *dest;
        
-       pthread_mutex_unlock(&spin);
+       thr_ret = pthread_mutex_unlock(&spin);
+       g_assert (thr_ret == 0);
+       
+       pthread_cleanup_pop (0);
        
        return(ret);
 }
@@ -98,14 +129,22 @@ gint32 InterlockedDecrement(volatile gint32 *dest)
 gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch)
 {
        gint32 ret;
+       int thr_ret;
        
        mono_once(&spin_once, spin_init);
-       pthread_mutex_lock(&spin);
+       
+       pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+                             (void *)&req_mutex);
+       thr_ret = pthread_mutex_lock(&spin);
+       g_assert (thr_ret == 0);
 
        ret=*dest;
        *dest=exch;
        
-       pthread_mutex_unlock(&spin);
+       thr_ret = pthread_mutex_unlock(&spin);
+       g_assert (thr_ret == 0);
+       
+       pthread_cleanup_pop (0);
        
        return(ret);
 }
@@ -113,14 +152,22 @@ gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch)
 gpointer InterlockedExchangePointer(volatile gpointer *dest, gpointer exch)
 {
        gpointer ret;
+       int thr_ret;
        
        mono_once(&spin_once, spin_init);
-       pthread_mutex_lock(&spin);
+       
+       pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+                             (void *)&spin);
+       thr_ret = pthread_mutex_lock(&spin);
+       g_assert (thr_ret == 0);
        
        ret=*dest;
        *dest=exch;
        
-       pthread_mutex_unlock(&spin);
+       thr_ret = pthread_mutex_unlock(&spin);
+       g_assert (thr_ret == 0);
+       
+       pthread_cleanup_pop (0);
        
        return(ret);
 }
@@ -128,15 +175,23 @@ gpointer InterlockedExchangePointer(volatile gpointer *dest, gpointer exch)
 gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add)
 {
        gint32 ret;
+       int thr_ret;
        
        mono_once(&spin_once, spin_init);
-       pthread_mutex_lock(&spin);
+       
+       pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+                             (void *)&spin);
+       thr_ret = pthread_mutex_lock(&spin);
+       g_assert (thr_ret == 0);
 
        ret= *dest;
        *dest+=add;
        
-       pthread_mutex_unlock(&spin);
-       
+       thr_ret = pthread_mutex_unlock(&spin);
+       g_assert (thr_ret == 0);
+
+       pthread_cleanup_pop (0);
+
        return(ret);
 }
 
index e3ed4613bf1161ff5947c57d702d64363774f67d..7f8553ce5285a829d61cfde7bd934a26c69ffe31 100644 (file)
@@ -31,8 +31,13 @@ static mono_mutexattr_t attr;
 
 static void attr_init(void)
 {
-       mono_mutexattr_init(&attr);
-       mono_mutexattr_settype(&attr, MONO_MUTEX_RECURSIVE);
+       int ret;
+       
+       ret = mono_mutexattr_init(&attr);
+       g_assert (ret == 0);
+       
+       ret = mono_mutexattr_settype(&attr, MONO_MUTEX_RECURSIVE);
+       g_assert (ret == 0);
 }
 
 /**
@@ -43,8 +48,11 @@ static void attr_init(void)
  */
 void InitializeCriticalSection(WapiCriticalSection *section)
 {
+       int ret;
+       
        mono_once(&attr_key_once, attr_init);
-       mono_mutex_init(&section->mutex, &attr);
+       ret = mono_mutex_init(&section->mutex, &attr);
+       g_assert (ret == 0);
 }
 
 /**
@@ -75,7 +83,10 @@ gboolean InitializeCriticalSectionAndSpinCount(WapiCriticalSection *section,
  */
 void DeleteCriticalSection(WapiCriticalSection *section)
 {
-       mono_mutex_destroy(&section->mutex);
+       int ret;
+       
+       ret = mono_mutex_destroy(&section->mutex);
+       g_assert (ret == 0);
 }
 
 /**
@@ -155,6 +166,9 @@ void EnterCriticalSection(WapiCriticalSection *section)
  */
 void LeaveCriticalSection(WapiCriticalSection *section)
 {
-       mono_mutex_unlock(&section->mutex);
+       int ret;
+       
+       ret = mono_mutex_unlock(&section->mutex);
+       g_assert (ret == 0);
 }
 
index 0aa7cbb34b1ff86f0a060a66689483550b5f02b1..09c10dcd3e13c78743499824968ca20ffeb39b83 100644 (file)
@@ -50,7 +50,10 @@ static void _wapi_daemon_request_response_internal (int fd,
         * rely on request turnaround time being minimal anyway, so
         * performance shouldnt suffer from the mutex.
         */
-       pthread_mutex_lock (&req_mutex);
+       pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+                             (void *)&req_mutex);
+       ret = pthread_mutex_lock (&req_mutex);
+       g_assert (ret == 0);
        
 #ifdef HAVE_MSG_NOSIGNAL
        ret=sendmsg (fd, msg, MSG_NOSIGNAL);
@@ -86,7 +89,10 @@ static void _wapi_daemon_request_response_internal (int fd,
                }
        }
 
-       pthread_mutex_unlock (&req_mutex);
+       ret = pthread_mutex_unlock (&req_mutex);
+       g_assert (ret == 0);
+       
+       pthread_cleanup_pop (0);
 }
 
 /* Send request on fd with filedescriptors, wait for response (called
index 18df1ad30b858caf76d3b5ba4ca4146e6f652d91..6b1e18042794932b83b262abf068c5f32e3eca06 100644 (file)
@@ -20,7 +20,10 @@ static mono_once_t error_key_once=MONO_ONCE_INIT;
 
 static void error_init(void)
 {
-       pthread_key_create(&error_key, NULL);
+       int ret;
+       
+       ret = pthread_key_create(&error_key, NULL);
+       g_assert (ret == 0);
 }
 
 /**
@@ -51,9 +54,12 @@ guint32 GetLastError(void)
  */
 void SetLastError(guint32 code)
 {
+       int ret;
+       
        /* Set the thread-local error code */
        mono_once(&error_key_once, error_init);
-       pthread_setspecific(error_key, GUINT_TO_POINTER(code));
+       ret = pthread_setspecific(error_key, GUINT_TO_POINTER(code));
+       g_assert (ret == 0);
 }
 
 guint32
index 8bd6556a83c7f1dde4c4781b782b6cbe09f5073b..d95be4b0c7b6c6a330d383ad5a5856d650c674fc 100644 (file)
@@ -115,6 +115,8 @@ gpointer CreateEvent(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean ma
        struct _WapiHandle_event *event_handle;
        gpointer handle;
        gboolean ok;
+       gpointer ret = NULL;
+       int thr_ret;
        
        mono_once (&event_ops_once, event_ops_init);
 
@@ -125,16 +127,19 @@ gpointer CreateEvent(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean ma
                return(NULL);
        }
        
-       _wapi_handle_lock_handle (handle);
+       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+                             handle);
+       thr_ret = _wapi_handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
                                (gpointer *)&event_handle, NULL);
        if(ok==FALSE) {
                g_warning (G_GNUC_PRETTY_FUNCTION
                           ": error looking up event handle %p", handle);
-               _wapi_handle_unlock_handle (handle);
-               return(NULL);
+               goto cleanup;
        }
+       ret = handle;
        
        event_handle->manual=manual;
 
@@ -147,9 +152,13 @@ gpointer CreateEvent(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean ma
                  handle);
 #endif
 
-       _wapi_handle_unlock_handle (handle);
+cleanup:
+       thr_ret = _wapi_handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
        
-       return(handle);
+       pthread_cleanup_pop (0);
+
+       return(ret);
 }
 
 /**
@@ -171,6 +180,7 @@ gboolean PulseEvent(gpointer handle)
 {
        struct _WapiHandle_event *event_handle;
        gboolean ok;
+       int thr_ret;
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
                                (gpointer *)&event_handle, NULL);
@@ -180,7 +190,10 @@ gboolean PulseEvent(gpointer handle)
                return(FALSE);
        }
        
-       _wapi_handle_lock_handle (handle);
+       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+                             handle);
+       thr_ret = _wapi_handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
 
 #ifdef DEBUG
        g_message(G_GNUC_PRETTY_FUNCTION ": Pulsing event handle %p", handle);
@@ -192,7 +205,10 @@ gboolean PulseEvent(gpointer handle)
                _wapi_handle_set_signal_state (handle, TRUE, FALSE);
        }
 
-       _wapi_handle_unlock_handle (handle);
+       thr_ret = _wapi_handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+       
+       pthread_cleanup_pop (0);
        
        if(event_handle->manual==TRUE) {
                /* For a manual-reset event, we're about to try and
@@ -212,9 +228,15 @@ gboolean PulseEvent(gpointer handle)
                          ": Obtained write lock on event handle %p", handle);
 #endif
 
-               _wapi_handle_lock_handle (handle);
+               pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle, handle);
+               thr_ret = _wapi_handle_lock_handle (handle);
+               g_assert (thr_ret == 0);
+               
                _wapi_handle_set_signal_state (handle, FALSE, FALSE);
-               _wapi_handle_unlock_handle (handle);
+
+               thr_ret = _wapi_handle_unlock_handle (handle);
+               g_assert (thr_ret == 0);
+               pthread_cleanup_pop (0);
        }
 
        return(TRUE);
@@ -233,6 +255,7 @@ gboolean ResetEvent(gpointer handle)
 {
        struct _WapiHandle_event *event_handle;
        gboolean ok;
+       int thr_ret;
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
                                (gpointer *)&event_handle, NULL);
@@ -247,26 +270,29 @@ gboolean ResetEvent(gpointer handle)
                  handle);
 #endif
 
-       _wapi_handle_lock_handle (handle);
+       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+                             handle);
+       thr_ret = _wapi_handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
+       
        if(_wapi_handle_issignalled (handle)==FALSE) {
-
 #ifdef DEBUG
                g_message(G_GNUC_PRETTY_FUNCTION
                          ": No need to reset event handle %p", handle);
 #endif
-
-               _wapi_handle_unlock_handle (handle);
-               return(TRUE);
-       }
-       
+       } else {
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION
-                 ": Obtained write lock on event handle %p", handle);
+               g_message(G_GNUC_PRETTY_FUNCTION
+                         ": Obtained write lock on event handle %p", handle);
 #endif
 
-       _wapi_handle_set_signal_state (handle, FALSE, FALSE);
-
-       _wapi_handle_unlock_handle (handle);
+               _wapi_handle_set_signal_state (handle, FALSE, FALSE);
+       }
+       
+       thr_ret = _wapi_handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+       
+       pthread_cleanup_pop (0);
        
        return(TRUE);
 }
@@ -289,6 +315,7 @@ gboolean SetEvent(gpointer handle)
 {
        struct _WapiHandle_event *event_handle;
        gboolean ok;
+       int thr_ret;
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
                                (gpointer *)&event_handle, NULL);
@@ -298,7 +325,10 @@ gboolean SetEvent(gpointer handle)
                return(FALSE);
        }
        
-       _wapi_handle_lock_handle (handle);
+       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+                             handle);
+       thr_ret = _wapi_handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
 
 #ifdef DEBUG
        g_message(G_GNUC_PRETTY_FUNCTION ": Setting event handle %p", handle);
@@ -310,7 +340,10 @@ gboolean SetEvent(gpointer handle)
                _wapi_handle_set_signal_state (handle, TRUE, FALSE);
        }
 
-       _wapi_handle_unlock_handle (handle);
+       thr_ret = _wapi_handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+       
+       pthread_cleanup_pop (0);
 
        return(TRUE);
 }
index f4e2cdf32795a9e87f026e381527b107483b7444..4a6870335ef9d245528ff28b37d3f987b43a6628 100644 (file)
@@ -83,17 +83,24 @@ extern gboolean _wapi_handle_process_fork (guint32 cmd, guint32 env,
                                           gpointer *thread_handle,
                                           guint32 *pid, guint32 *tid);
 
-extern gboolean _wapi_handle_process_kill (gpointer process_handle,
-                                          guint32 signo,
+extern gboolean _wapi_handle_process_kill (pid_t pid, guint32 signo,
                                           gint *err);
 
 static inline struct _WapiHandleShared_list *_wapi_handle_get_shared_segment (guint32 segment)
 {
        struct _WapiHandleShared_list *shared;
+       int thr_ret;
+       
+       pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+                             (void *)&_wapi_shared_mutex);
+       thr_ret = pthread_mutex_lock (&_wapi_shared_mutex);
+       g_assert (thr_ret == 0);
        
-       pthread_mutex_lock (&_wapi_shared_mutex);
        shared=_wapi_shared_data[segment];
-       pthread_mutex_unlock (&_wapi_shared_mutex);
+
+       thr_ret = pthread_mutex_unlock (&_wapi_shared_mutex);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
 
        return(shared);
 }
@@ -101,16 +108,26 @@ static inline struct _WapiHandleShared_list *_wapi_handle_get_shared_segment (gu
 static inline struct _WapiHandlePrivate_list *_wapi_handle_get_private_segment (guint32 segment)
 {
        struct _WapiHandlePrivate_list *priv;
+       int thr_ret;
+       
+       pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+                             (void *)&_wapi_shared_mutex);
+       thr_ret = pthread_mutex_lock (&_wapi_shared_mutex);
+       g_assert (thr_ret == 0);
        
-       pthread_mutex_lock (&_wapi_shared_mutex);
        priv=_wapi_private_data[segment];
-       pthread_mutex_unlock (&_wapi_shared_mutex);
+       
+       thr_ret = pthread_mutex_unlock (&_wapi_shared_mutex);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
        
        return(priv);
 }
 
 static inline void _wapi_handle_ensure_mapped (guint32 segment)
 {
+       int thr_ret;
+       
 #ifdef DEBUG
        g_message (G_GNUC_PRETTY_FUNCTION ": checking segment %d is mapped",
                   segment);
@@ -127,7 +144,10 @@ static inline void _wapi_handle_ensure_mapped (guint32 segment)
                return;
        }
        
-       pthread_mutex_lock (&_wapi_shared_mutex);
+       pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+                             (void *)&_wapi_shared_mutex);
+       thr_ret = pthread_mutex_lock (&_wapi_shared_mutex);
+       g_assert (thr_ret == 0);
        
        if(segment>=_wapi_shm_mapped_segments) {
                /* Need to extend the arrays.  We can't use g_renew
@@ -172,7 +192,9 @@ static inline void _wapi_handle_ensure_mapped (guint32 segment)
                }
        }
 
-       pthread_mutex_unlock (&_wapi_shared_mutex);
+       thr_ret = pthread_mutex_unlock (&_wapi_shared_mutex);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
 }
 
 static inline void _wapi_handle_segment (gpointer handle, guint32 *segment,
@@ -211,6 +233,7 @@ static inline void _wapi_handle_set_signal_state (gpointer handle,
        guint32 idx;
        guint32 segment;
        struct _WapiHandleShared *shared_handle;
+       int thr_ret;
        
        _wapi_handle_segment (handle, &segment, &idx);
        shared_handle=&_wapi_handle_get_shared_segment (segment)->handles[idx];
@@ -228,9 +251,11 @@ static inline void _wapi_handle_set_signal_state (gpointer handle,
                shared_handle->signalled=state;
                
                if(broadcast==TRUE) {
-                       pthread_cond_broadcast (&shared_handle->signal_cond);
+                       thr_ret = pthread_cond_broadcast (&shared_handle->signal_cond);
+                       g_assert (thr_ret == 0);
                } else {
-                       pthread_cond_signal (&shared_handle->signal_cond);
+                       thr_ret = pthread_cond_signal (&shared_handle->signal_cond);
+                       g_assert (thr_ret == 0);
                }
 
                /* Tell everyone blocking on multiple handles that something
@@ -239,9 +264,17 @@ static inline void _wapi_handle_set_signal_state (gpointer handle,
 #if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
                {
                        struct _WapiHandleShared_list *segment0=_wapi_handle_get_shared_segment (0);
-                       mono_mutex_lock (&segment0->signal_mutex);
-                       pthread_cond_broadcast (&segment0->signal_cond);
-                       mono_mutex_unlock (&segment0->signal_mutex);
+                       
+                       pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup, (void *)&segment0->signal_mutex);
+                       thr_ret = mono_mutex_lock (&segment0->signal_mutex);
+                       g_assert (thr_ret == 0);
+                       
+                       thr_ret = pthread_cond_broadcast (&segment0->signal_cond);
+                       g_assert (thr_ret == 0);
+                       
+                       thr_ret = mono_mutex_unlock (&segment0->signal_mutex);
+                       g_assert (thr_ret == 0);
+                       pthread_cleanup_pop (0);
                }
 #else
                {
@@ -251,14 +284,20 @@ static inline void _wapi_handle_set_signal_state (gpointer handle,
                        g_message (G_GNUC_PRETTY_FUNCTION ": lock global signal mutex");
 #endif
 
-                       mono_mutex_lock (&segment0->signal_mutex);
-                       pthread_cond_broadcast (&segment0->signal_cond);
+                       pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup, (void *)&segment0->signal_mutex);
+                       thr_ret = mono_mutex_lock (&segment0->signal_mutex);
+                       g_assert (thr_ret == 0);
+                       
+                       thr_ret = pthread_cond_broadcast (&segment0->signal_cond);
+                       g_assert (thr_ret == 0);
 
 #ifdef DEBUG
                        g_message (G_GNUC_PRETTY_FUNCTION ": unlock global signal mutex");
 #endif
 
-                       mono_mutex_unlock (&segment0->signal_mutex);
+                       thr_ret = mono_mutex_unlock (&segment0->signal_mutex);
+                       g_assert (thr_ret == 0);
+                       pthread_cleanup_pop (0);
                }
 #endif /* _POSIX_THREAD_PROCESS_SHARED */
        } else {
@@ -288,7 +327,8 @@ static inline int _wapi_handle_lock_signal_mutex (void)
 #endif /* _POSIX_THREAD_PROCESS_SHARED */
 }
 
-static inline int _wapi_handle_unlock_signal_mutex (void)
+/* the parameter makes it easier to call from a pthread cleanup handler */
+static inline int _wapi_handle_unlock_signal_mutex (void *unused)
 {
 #ifdef DEBUG
        g_message (G_GNUC_PRETTY_FUNCTION ": unlock global signal mutex");
@@ -309,6 +349,8 @@ static inline int _wapi_handle_lock_handle (gpointer handle)
        g_message (G_GNUC_PRETTY_FUNCTION ": locking handle %p", handle);
 #endif
 
+       _wapi_handle_ref (handle);
+       
        _wapi_handle_segment (handle, &segment, &idx);
        
        return(mono_mutex_lock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex));
@@ -318,6 +360,7 @@ static inline int _wapi_handle_unlock_handle (gpointer handle)
 {
        guint32 idx;
        guint32 segment;
+       int ret;
        
 #ifdef DEBUG
        g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handle %p", handle);
@@ -325,7 +368,11 @@ static inline int _wapi_handle_unlock_handle (gpointer handle)
 
        _wapi_handle_segment (handle, &segment, &idx);
        
-       return(mono_mutex_unlock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex));
+       ret = mono_mutex_unlock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
+
+       _wapi_handle_unref (handle);
+       
+       return(ret);
 }
 
 #endif /* _WAPI_HANDLES_PRIVATE_H_ */
index d470a3a6e856cedc1a9f31eff6f276b5136ebc17..019ae348bb33141a449250be40c8ca22180a228e 100644 (file)
@@ -82,7 +82,8 @@ static void shared_init (void)
        struct sockaddr_un shared_socket_address;
        gboolean tried_once=FALSE;
        int ret;
-
+       int thr_ret;
+       
        _wapi_shared_data=g_new0 (struct _WapiHandleShared_list *, 1);
        _wapi_private_data=g_new0 (struct _WapiHandlePrivate_list *, 1);
        
@@ -159,17 +160,26 @@ attach_again:
        _wapi_private_data[0]=g_new0 (struct _WapiHandlePrivate_list, 1);
        _wapi_shm_mapped_segments=1;
 
-       pthread_mutexattr_init (&mutex_shared_attr);
-       pthread_condattr_init (&cond_shared_attr);
-
+       thr_ret = pthread_mutexattr_init (&mutex_shared_attr);
+       g_assert (thr_ret == 0);
+       
+       thr_ret = pthread_condattr_init (&cond_shared_attr);
+       g_assert (thr_ret == 0);
+       
 #if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
-       pthread_mutexattr_setpshared (&mutex_shared_attr,
-                                     PTHREAD_PROCESS_SHARED);
-       pthread_condattr_setpshared (&cond_shared_attr,
-                                    PTHREAD_PROCESS_SHARED);
+       thr_ret = pthread_mutexattr_setpshared (&mutex_shared_attr,
+                                               PTHREAD_PROCESS_SHARED);
+       g_assert (thr_ret == 0);
+       
+       thr_ret = pthread_condattr_setpshared (&cond_shared_attr,
+                                              PTHREAD_PROCESS_SHARED);
+       g_assert (thr_ret == 0);
 #else
-       pthread_cond_init(&_wapi_private_data[0]->signal_cond, NULL);
-       mono_mutex_init(&_wapi_private_data[0]->signal_mutex, NULL);
+       thr_ret = pthread_cond_init(&_wapi_private_data[0]->signal_cond, NULL);
+       g_assert (thr_ret == 0);
+       
+       thr_ret = mono_mutex_init(&_wapi_private_data[0]->signal_mutex, NULL);
+       g_assert (thr_ret == 0);
 #endif
 }
 
@@ -227,6 +237,7 @@ guint32 _wapi_handle_new_internal (WapiHandleType type)
        guint32 segment, idx;
        guint32 i, j;
        static guint32 last=1;
+       int thr_ret;
        
        /* A linear scan should be fast enough.  Start from the last
         * allocation, assuming that handles are allocated more often
@@ -258,11 +269,17 @@ again:
                                shared->type=type;
                                shared->signalled=FALSE;
 #if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
-                               mono_mutex_init (&shared->signal_mutex, &mutex_shared_attr);
-                               pthread_cond_init (&shared->signal_cond, &cond_shared_attr);
+                               thr_ret = mono_mutex_init (&shared->signal_mutex, &mutex_shared_attr);
+                               g_assert (thr_ret == 0);
+                               
+                               thr_ret = pthread_cond_init (&shared->signal_cond, &cond_shared_attr);
+                               g_assert (thr_ret == 0);
 #else
-                               pthread_cond_init(&shared->signal_cond, NULL);
-                               mono_mutex_init(&shared->signal_mutex, NULL);
+                               thr_ret = pthread_cond_init(&shared->signal_cond, NULL);
+                               g_assert (thr_ret == 0);
+                               
+                               thr_ret = mono_mutex_init(&shared->signal_mutex, NULL);
+                               g_assert (thr_ret == 0);
 #endif
                                
                                return(_wapi_handle_index (i, j));
@@ -285,13 +302,14 @@ gpointer _wapi_handle_new (WapiHandleType type)
 {
        static mono_once_t shared_init_once = MONO_ONCE_INIT;
        static pthread_mutex_t scan_mutex=PTHREAD_MUTEX_INITIALIZER;
-       guint32 handle_idx, idx, segment;
+       guint32 handle_idx = 0, idx, segment;
        gpointer handle;
        WapiHandleRequest new={0};
        WapiHandleResponse new_resp={0};
 #if HAVE_BOEHM_GC
        gboolean tried_collect=FALSE;
 #endif
+       int thr_ret;
        
        mono_once (&shared_init_once, shared_init);
 
@@ -311,7 +329,11 @@ again:
                        g_assert_not_reached ();
                }
        } else {
-               pthread_mutex_lock (&scan_mutex);
+               pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+                                     (void *)&scan_mutex);
+               thr_ret = pthread_mutex_lock (&scan_mutex);
+               g_assert (thr_ret == 0);
+               
                handle_idx=_wapi_handle_new_internal (type);
                if(handle_idx==0) {
                        /* Try and get a new segment, and have another go */
@@ -331,7 +353,10 @@ again:
                
                _wapi_handle_segment (GUINT_TO_POINTER (handle_idx), &segment, &idx);
                _wapi_handle_get_shared_segment (segment)->handles[idx].ref++;
-               pthread_mutex_unlock (&scan_mutex);
+
+               thr_ret = pthread_mutex_unlock (&scan_mutex);
+               g_assert (thr_ret == 0);
+               pthread_cleanup_pop (0);
        }
                
        if(handle_idx==0) {
@@ -364,8 +389,11 @@ again:
        }
        
 #if !defined(_POSIX_THREAD_PROCESS_SHARED) || _POSIX_THREAD_PROCESS_SHARED == -1
-       mono_mutex_init (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex, &mutex_shared_attr);
-       pthread_cond_init (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_cond, &cond_shared_attr);
+       thr_ret = mono_mutex_init (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex, &mutex_shared_attr);
+       g_assert (thr_ret == 0);
+       
+       thr_ret = pthread_cond_init (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_cond, &cond_shared_attr);
+       g_assert (thr_ret == 0);
 #endif
        handle=GUINT_TO_POINTER (handle_idx);
 
@@ -380,7 +408,7 @@ gboolean _wapi_lookup_handle (gpointer handle, WapiHandleType type,
                              gpointer *shared, gpointer *private)
 {
        struct _WapiHandleShared *shared_handle_data;
-       struct _WapiHandlePrivate *private_handle_data;
+       struct _WapiHandlePrivate *private_handle_data = NULL;
        guint32 idx;
        guint32 segment;
 
@@ -591,11 +619,13 @@ void _wapi_handle_ref (gpointer handle)
        }
 }
 
+/* The handle must not be locked on entry to this function */
 void _wapi_handle_unref (gpointer handle)
 {
        guint32 idx, segment;
-       gboolean destroy;
-
+       gboolean destroy = FALSE;
+       int thr_ret;
+       
        _wapi_handle_segment (handle, &segment, &idx);
        
        if(shared==TRUE) {
@@ -639,18 +669,22 @@ void _wapi_handle_unref (gpointer handle)
                if(shared==FALSE) {
                        _wapi_handle_ops_close_shared (handle);
 
-                       mono_mutex_destroy (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
-                       pthread_cond_destroy (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_cond);
                        memset (&_wapi_handle_get_shared_segment (segment)->handles[idx].u, '\0', sizeof(_wapi_handle_get_shared_segment (segment)->handles[idx].u));
-               
-               }
-               else {
-                       mono_mutex_destroy (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
-                       pthread_cond_destroy (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_cond);
                }
 
                _wapi_handle_ops_close_private (handle);
                _wapi_handle_get_shared_segment (segment)->handles[idx].type=WAPI_HANDLE_UNUSED;
+               
+               /* Destroy the mutex and cond var.  We hope nobody
+                * tried to grab them between the handle unlock and
+                * now, but pthreads doesn't have a
+                * "unlock_and_destroy" atomic function.
+                */
+               thr_ret = mono_mutex_destroy (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
+               g_assert (thr_ret == 0);
+                       
+               thr_ret = pthread_cond_destroy (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_cond);
+               g_assert (thr_ret == 0);
        }
 }
 
@@ -684,7 +718,7 @@ static void _wapi_handle_scratch_expand (void)
 static guint32 _wapi_handle_scratch_locate_space (guint32 bytes)
 {
        guint32 idx=0, last_idx=0;
-       struct _WapiScratchHeader *hdr, *last_hdr;
+       struct _WapiScratchHeader *hdr, *last_hdr = NULL;
        gboolean last_was_free=FALSE;
        guchar *storage=_wapi_shared_scratch->scratch_data;
        
@@ -860,9 +894,11 @@ guint32 _wapi_handle_scratch_store_internal (guint32 bytes, gboolean *remap)
 
 guint32 _wapi_handle_scratch_store (gconstpointer data, guint32 bytes)
 {
-       guint32 idx, store_bytes;
+       guint32 idx = 0, store_bytes;
        gboolean remap;
-
+       int thr_ret;
+       guint32 ret = 0;
+       
 #ifdef DEBUG
        g_message (G_GNUC_PRETTY_FUNCTION ": storing %d bytes", bytes);
 #endif
@@ -875,8 +911,11 @@ guint32 _wapi_handle_scratch_store (gconstpointer data, guint32 bytes)
        /* Align bytes to 32 bits (needed for sparc at least) */
        store_bytes = (((bytes) + 3) & (~3));
 
-       pthread_mutex_lock (&_wapi_scratch_mutex);
-
+       pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+                             (void *)&_wapi_scratch_mutex);
+       thr_ret = pthread_mutex_lock (&_wapi_scratch_mutex);
+       g_assert (thr_ret == 0);
+       
        if(shared==TRUE) {
                WapiHandleRequest scratch={0};
                WapiHandleResponse scratch_resp={0};
@@ -907,11 +946,11 @@ guint32 _wapi_handle_scratch_store (gconstpointer data, guint32 bytes)
                idx=_wapi_handle_scratch_store_internal (store_bytes, &remap);
                if(idx==0) {
                        /* Failed to allocate space */
-                       pthread_mutex_unlock (&_wapi_scratch_mutex);
-                       return(0);
+                       goto cleanup;
                }
        }
-
+       ret = idx;
+       
 #ifdef DEBUG
        g_message (G_GNUC_PRETTY_FUNCTION
                   ": stored [%s] at %d (len %d, aligned len %d)",
@@ -920,9 +959,12 @@ guint32 _wapi_handle_scratch_store (gconstpointer data, guint32 bytes)
        
        memcpy (&_wapi_shared_scratch->scratch_data[idx], data, bytes);
 
-       pthread_mutex_unlock (&_wapi_scratch_mutex);
+cleanup:
+       thr_ret = pthread_mutex_unlock (&_wapi_scratch_mutex);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
        
-       return(idx);
+       return(ret);
 }
 
 guint32 _wapi_handle_scratch_store_string_array (gchar **data)
@@ -969,12 +1011,16 @@ gpointer _wapi_handle_scratch_lookup (guint32 idx)
        struct _WapiScratchHeader *hdr;
        gpointer ret;
        guchar *storage;
+       int thr_ret;
        
        if(idx < HDRSIZE || idx > _wapi_shared_scratch->data_len) {
                return(NULL);
        }
 
-       pthread_mutex_lock (&_wapi_scratch_mutex);
+       pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+                             (void *)&_wapi_scratch_mutex);
+       thr_ret = pthread_mutex_lock (&_wapi_scratch_mutex);
+       g_assert (thr_ret == 0);
        
        storage=_wapi_shared_scratch->scratch_data;
        
@@ -982,7 +1028,9 @@ gpointer _wapi_handle_scratch_lookup (guint32 idx)
        ret=g_malloc0 (hdr->length+1);
        memcpy (ret, &storage[idx], hdr->length);
 
-       pthread_mutex_unlock (&_wapi_scratch_mutex);
+       thr_ret = pthread_mutex_unlock (&_wapi_scratch_mutex);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
 
        return(ret);
 }
@@ -1040,12 +1088,16 @@ void _wapi_handle_scratch_delete_internal (guint32 idx)
 {
        struct _WapiScratchHeader *hdr;
        guchar *storage;
+       int thr_ret;
        
        if(idx < HDRSIZE || idx > _wapi_shared_scratch->data_len) {
                return;
        }
 
-       pthread_mutex_lock (&_wapi_scratch_mutex);
+       pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+                             (void *)&_wapi_scratch_mutex);
+       thr_ret = pthread_mutex_lock (&_wapi_scratch_mutex);
+       g_assert (thr_ret == 0);
        
        storage=_wapi_shared_scratch->scratch_data;
        
@@ -1057,7 +1109,9 @@ void _wapi_handle_scratch_delete_internal (guint32 idx)
         * free, but the _store() function will do that anyway.
         */
 
-       pthread_mutex_unlock (&_wapi_scratch_mutex);
+       thr_ret = pthread_mutex_unlock (&_wapi_scratch_mutex);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
 }
 
 void _wapi_handle_scratch_delete (guint32 idx)
@@ -1241,6 +1295,7 @@ gboolean _wapi_handle_count_signalled_handles (guint32 numhandles,
 {
        guint32 count, i, iter=0;
        gboolean ret;
+       int thr_ret;
        
        /* Lock all the handles, with backoff */
 again:
@@ -1265,7 +1320,8 @@ again:
 
                        while(i--) {
                                _wapi_handle_segment (handles[i], &segment, &idx);
-                               mono_mutex_unlock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
+                               thr_ret = mono_mutex_unlock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
+                               g_assert (thr_ret == 0);
                        }
 
                        /* If iter ever reaches 100 the nanosleep will
@@ -1302,6 +1358,8 @@ again:
        for(i=0; i<numhandles; i++) {
                guint32 idx, segment;
 
+               _wapi_handle_ref (handles[i]);
+               
                _wapi_handle_segment (handles[i], &segment, &idx);
                
 #ifdef DEBUG
@@ -1348,6 +1406,7 @@ again:
 void _wapi_handle_unlock_handles (guint32 numhandles, gpointer *handles)
 {
        guint32 i;
+       int thr_ret;
        
        for(i=0; i<numhandles; i++) {
                guint32 idx, segment;
@@ -1359,7 +1418,10 @@ void _wapi_handle_unlock_handles (guint32 numhandles, gpointer *handles)
                           handles[i]);
 #endif
 
-               mono_mutex_unlock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
+               thr_ret = mono_mutex_unlock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
+               g_assert (thr_ret == 0);
+
+               _wapi_handle_unref (handles[i]);
        }
 }
 
@@ -1561,7 +1623,7 @@ gboolean _wapi_handle_process_fork (guint32 cmd, guint32 env, guint32 dir,
 }
 
 gboolean
-_wapi_handle_process_kill (gpointer process, guint32 signo, gint *errnum)
+_wapi_handle_process_kill (pid_t process, guint32 signo, gint *errnum)
 {
        WapiHandleRequest killproc = {0};
        WapiHandleResponse killprocresp = {0};
@@ -1573,7 +1635,7 @@ _wapi_handle_process_kill (gpointer process, guint32 signo, gint *errnum)
        }
 
        killproc.type = WapiHandleRequestType_ProcessKill;
-       killproc.u.process_kill.pid = GPOINTER_TO_UINT (process);
+       killproc.u.process_kill.pid = process;
        killproc.u.process_kill.signo = signo;
        
        _wapi_daemon_request_response (daemon_sock, &killproc, &killprocresp);
index 7ca68844031c40ed72d93000f610c353edddb61b..4861d4bd19b5c6a9ab645ae05bc07705e0298076 100644 (file)
@@ -1523,7 +1523,9 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
        mode_t perms=convert_perms(sharemode);
        gchar *filename;
        int ret;
-
+       int thr_ret;
+       gpointer cf_ret = INVALID_HANDLE_VALUE;
+       
        mono_once (&io_ops_once, io_ops_init);
        
        if(name==NULL) {
@@ -1580,7 +1582,10 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
                return(INVALID_HANDLE_VALUE);
        }
 
-       _wapi_handle_lock_handle (handle);
+       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+                             handle);
+       thr_ret = _wapi_handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
                                (gpointer *)&file_handle,
@@ -1588,11 +1593,9 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
        if(ok==FALSE) {
                g_warning (G_GNUC_PRETTY_FUNCTION
                           ": error looking up file handle %p", handle);
-               _wapi_handle_unlock_handle (handle);
-               g_free (filename);
-
-               return(INVALID_HANDLE_VALUE);
+               goto cleanup;
        }
+       cf_ret = handle;
 
        file_private_handle->fd=ret;
        file_private_handle->assigned=TRUE;
@@ -1614,10 +1617,14 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
                  file_private_handle->fd);
 #endif
 
-       _wapi_handle_unlock_handle (handle);
+cleanup:
+       thr_ret = _wapi_handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
+       
        g_free (filename);
        
-       return(handle);
+       return(cf_ret);
 }
 
 /**
@@ -1849,8 +1856,9 @@ static gpointer stdhandle_create (int fd, const guchar *name)
        struct _WapiHandle_file *file_handle;
        struct _WapiHandlePrivate_file *file_private_handle;
        gboolean ok;
-       gpointer handle;
+       gpointer handle, ret = NULL;
        int flags;
+       int thr_ret;
        
 #ifdef DEBUG
        g_message(G_GNUC_PRETTY_FUNCTION ": creating standard handle type %s",
@@ -1878,7 +1886,10 @@ static gpointer stdhandle_create (int fd, const guchar *name)
                return(NULL);
        }
 
-       _wapi_handle_lock_handle (handle);
+       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+                             handle);
+       thr_ret = _wapi_handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_CONSOLE,
                                (gpointer *)&file_handle,
@@ -1886,9 +1897,9 @@ static gpointer stdhandle_create (int fd, const guchar *name)
        if(ok==FALSE) {
                g_warning (G_GNUC_PRETTY_FUNCTION
                           ": error looking up console handle %p", handle);
-               _wapi_handle_unlock_handle (handle);
-               return(NULL);
+               goto cleanup;
        }
+       ret = handle;
        
        file_private_handle->fd=fd;
        file_private_handle->assigned=TRUE;
@@ -1904,9 +1915,12 @@ static gpointer stdhandle_create (int fd, const guchar *name)
                  handle, file_private_handle->fd);
 #endif
 
-       _wapi_handle_unlock_handle (handle);
+cleanup:
+       thr_ret = _wapi_handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
 
-       return(handle);
+       return(ret);
 }
 
 static void stdhandle_init (void)
@@ -2415,7 +2429,10 @@ static pthread_key_t file_key;
 
 static void file_once_init (void)
 {
-       pthread_key_create (&file_key, NULL);
+       int ret;
+       
+       ret = pthread_key_create (&file_key, NULL);
+       g_assert (ret == 0);
 }
 
 static int file_select (const struct dirent *dir)
@@ -2433,10 +2450,12 @@ static int file_select (const struct dirent *dir)
 gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
 {
        struct _WapiHandlePrivate_find *find_handle;
-       gpointer handle;
+       gpointer handle, find_ret = INVALID_HANDLE_VALUE;
        gboolean ok;
        gchar *utf8_pattern = NULL, *dir_part, *entry_part;
        int result;
+       int thr_ret;
+       gboolean unref = FALSE;
        
        mono_once (&file_key_once, file_once_init);
        
@@ -2482,17 +2501,18 @@ gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
                return(INVALID_HANDLE_VALUE);
        }
 
-       _wapi_handle_lock_handle (handle);
+       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+                             handle);
+       thr_ret = _wapi_handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FIND, NULL,
                                (gpointer *)&find_handle);
        if(ok==FALSE) {
                g_warning (G_GNUC_PRETTY_FUNCTION
                           ": error looking up find handle %p", handle);
-               _wapi_handle_unlock_handle (handle);
                g_free (utf8_pattern);
-               
-               return(INVALID_HANDLE_VALUE);
+               goto cleanup;
        }
 
        /* The pattern can specify a directory or a set of files.
@@ -2538,9 +2558,10 @@ gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
                }
                
                g_free (dir_part);
-               _wapi_handle_unlock_handle (handle);
-               _wapi_handle_unref (handle);
-               return(INVALID_HANDLE_VALUE);
+
+               unref = TRUE;
+               
+               goto cleanup;
        }
        
 #ifdef DEBUG
@@ -2551,16 +2572,30 @@ gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
        find_handle->num = result;
        find_handle->count = 0;
 
-       if (!FindNextFile (handle, find_data)) {
-               _wapi_handle_unlock_handle (handle);
+       find_ret = handle;
+
+cleanup:
+       thr_ret = _wapi_handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
+
+       /* FindNextFile has to be called after unlocking the handle,
+        * because it wants to lock the handle itself
+        */
+       if (find_ret != INVALID_HANDLE_VALUE &&
+           !FindNextFile (handle, find_data)) {
                FindClose (handle);
                SetLastError (ERROR_NO_MORE_FILES);
-               return(INVALID_HANDLE_VALUE);
        }
 
-       _wapi_handle_unlock_handle (handle);
-
-       return (handle);
+       /* Must not call _wapi_handle_unref() with the handle already
+        * locked
+        */
+       if (unref) {
+               _wapi_handle_unref (handle);
+       }
+       
+       return (find_ret);
 }
 
 gboolean FindNextFile (gpointer handle, WapiFindData *find_data)
@@ -2573,6 +2608,8 @@ gboolean FindNextFile (gpointer handle, WapiFindData *find_data)
        gunichar2 *utf16_basename;
        time_t create_time;
        glong bytes;
+       int thr_ret;
+       gboolean ret = FALSE;
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FIND, NULL,
                                (gpointer *)&find_handle);
@@ -2583,10 +2620,15 @@ gboolean FindNextFile (gpointer handle, WapiFindData *find_data)
                return(FALSE);
        }
 
+       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+                             handle);
+       thr_ret = _wapi_handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
+       
 retry:
        if (find_handle->count >= find_handle->num) {
                SetLastError (ERROR_NO_MORE_FILES);
-               return FALSE;
+               goto cleanup;
        }
 
        /* stat next match */
@@ -2598,8 +2640,7 @@ retry:
 #endif
 
                g_free (filename);
-               SetLastError (ERROR_NO_MORE_FILES);
-               return FALSE;
+               goto retry;
        }
 
        /* Check for dangling symlinks, and ignore them (principle of
@@ -2662,7 +2703,8 @@ retry:
                g_free (utf8_filename);
                goto retry;
        }
-
+       ret = TRUE;
+       
        /* utf16 is 2 * utf8 */
        bytes *= 2;
 
@@ -2680,7 +2722,12 @@ retry:
        g_free (utf8_filename);
        g_free (utf16_basename);
 
-       return TRUE;
+cleanup:
+       thr_ret = _wapi_handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
+       
+       return(ret);
 }
 
 /**
@@ -2696,6 +2743,7 @@ gboolean FindClose (gpointer handle)
        struct _WapiHandlePrivate_find *find_handle;
        gboolean ok;
        int i;
+       int thr_ret;
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FIND, NULL,
                                (gpointer *)&find_handle);
@@ -2705,16 +2753,25 @@ gboolean FindClose (gpointer handle)
                SetLastError (ERROR_INVALID_HANDLE);
                return(FALSE);
        }
+
+       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+                             handle);
+       thr_ret = _wapi_handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
        
        for(i = 0; i < find_handle->num; i++) {
                free (find_handle->namelist[i]);
        }
        free (find_handle->namelist);
        g_free (find_handle->dir_part);
+
+       thr_ret = _wapi_handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
        
        _wapi_handle_unref (handle);
-
-       return TRUE;
+       
+       return(TRUE);
 }
 
 /**
@@ -3088,6 +3145,9 @@ gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe,
        gboolean ok;
        int filedes[2];
        int ret;
+       int thr_ret;
+       gboolean unref_read = FALSE, unref_write = FALSE;
+       gboolean cp_ret = FALSE;
        
        mono_once (&io_ops_once, io_ops_init);
        
@@ -3117,45 +3177,50 @@ gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe,
                return(FALSE);
        }
        
-       _wapi_handle_lock_handle (read_handle);
+       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+                             read_handle);
+       thr_ret = _wapi_handle_lock_handle (read_handle);
+       g_assert (thr_ret == 0);
 
        ok=_wapi_lookup_handle (read_handle, WAPI_HANDLE_PIPE,
                                (gpointer *)&pipe_read_handle,
                                (gpointer *)&pipe_read_private_handle);
        if(ok==FALSE) {
                g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up pipe handle %p", read_handle);
-               _wapi_handle_unlock_handle (read_handle);
                close (filedes[0]);
                close (filedes[1]);
-               return(FALSE);
+               goto cleanup;
        }
        
        write_handle=_wapi_handle_new (WAPI_HANDLE_PIPE);
        if(write_handle==_WAPI_HANDLE_INVALID) {
                g_warning (G_GNUC_PRETTY_FUNCTION
                           ": error creating pipe write handle");
-               _wapi_handle_unlock_handle (read_handle);
-               _wapi_handle_unref (read_handle);
+               unref_read = TRUE;
                
                close (filedes[0]);
                close (filedes[1]);
-               return(FALSE);
+               goto cleanup;
        }
        
-       _wapi_handle_lock_handle (write_handle);
+       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+                             write_handle);
+       thr_ret = _wapi_handle_lock_handle (write_handle);
+       g_assert (thr_ret == 0);
 
        ok=_wapi_lookup_handle (write_handle, WAPI_HANDLE_PIPE,
                                (gpointer *)&pipe_write_handle,
                                (gpointer *)&pipe_write_private_handle);
        if(ok==FALSE) {
                g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up pipe handle %p", read_handle);
-               _wapi_handle_unlock_handle (read_handle);
-               _wapi_handle_unref (read_handle);
-               _wapi_handle_unlock_handle (write_handle);
+               unref_read = TRUE;
+               unref_write = TRUE;
+               
                close (filedes[0]);
                close (filedes[1]);
-               return(FALSE);
+               goto write_cleanup;
        }
+       cp_ret = TRUE;
        
        pipe_read_private_handle->fd=filedes[0];
        pipe_read_private_handle->assigned=TRUE;
@@ -3169,16 +3234,33 @@ gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe,
        
        *writepipe=write_handle;
 
-       _wapi_handle_unlock_handle (read_handle);
-       _wapi_handle_unlock_handle (write_handle);
-
 #ifdef DEBUG
        g_message (G_GNUC_PRETTY_FUNCTION
                   ": Returning pipe: read handle %p, write handle %p",
                   read_handle, write_handle);
 #endif
 
-       return(TRUE);
+write_cleanup:
+       thr_ret =_wapi_handle_unlock_handle (write_handle);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
+
+cleanup:
+       thr_ret =_wapi_handle_unlock_handle (read_handle);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
+
+       /* Must not call _wapi_handle_unref() with the handle already
+        * locked
+        */
+       if (unref_read) {
+               _wapi_handle_unref (read_handle);
+       }
+       if (unref_write) {
+               _wapi_handle_unref (write_handle);
+       }
+       
+       return(cp_ret);
 }
 
 guint32 GetTempPath (guint32 len, gunichar2 *buf)
@@ -3234,6 +3316,8 @@ _wapi_io_add_callback (gpointer handle,
        struct _WapiHandle_file *file_handle;
        struct _WapiHandlePrivate_file *file_private_handle;
        gboolean ok;
+       int thr_ret;
+       gboolean ret = FALSE;
        
        ok = _wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
                                  (gpointer *) &file_handle,
@@ -3251,15 +3335,24 @@ _wapi_io_add_callback (gpointer handle,
                return FALSE;
        }
 
-       _wapi_handle_lock_handle (handle);
+       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+                             handle);
+       thr_ret = _wapi_handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
+       
        if (file_private_handle->callback != NULL) {
                SetLastError (ERROR_INVALID_PARAMETER);
-               return FALSE;
+               goto cleanup;
        }
-
+       ret = TRUE;
+       
        file_private_handle->callback = callback;
-       _wapi_handle_unlock_handle (handle);
 
-       return TRUE;
+cleanup:
+       thr_ret = _wapi_handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
+
+       return(ret);
 }
 
index 17a958cbe1b2ef0fe4b646c1bfacf2668323fb0c..bfbfd9bee4fbca238d8d58750463b1dbc06e8525 100644 (file)
@@ -68,13 +68,22 @@ pthread_mutex_timedlock (pthread_mutex_t *mutex, const struct timespec *timeout)
 int
 mono_once (mono_once_t *once, void (*once_init) (void))
 {
+       int thr_ret;
+       
        if (!once->complete) {
-               pthread_mutex_lock (&once->mutex);
+               pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+                                     (void *)&once->mutex);
+               thr_ret = pthread_mutex_lock (&once->mutex);
+               g_assert (thr_ret == 0);
+               
                if (!once->complete) {
                        once_init ();
                        once->complete = TRUE;
                }
-               pthread_mutex_unlock (&once->mutex);
+               thr_ret = pthread_mutex_unlock (&once->mutex);
+               g_assert (thr_ret == 0);
+               
+               pthread_cleanup_pop (0);
        }
        
        return 0;
@@ -156,20 +165,24 @@ mono_mutexattr_destroy (mono_mutexattr_t *attr)
 int
 mono_mutex_init (mono_mutex_t *mutex, const mono_mutexattr_t *attr)
 {
+       int ret;
+       int thr_ret;
+       
        mutex->waiters = 0;
        mutex->depth = 0;
        mutex->owner = MONO_THREAD_NONE;
        
        if (!attr || attr->type == MONO_MUTEX_NORMAL) {
                mutex->type = MONO_MUTEX_NORMAL;
-               pthread_mutex_init (&mutex->mutex, NULL);
+               ret = pthread_mutex_init (&mutex->mutex, NULL);
        } else {
                mutex->type = MONO_MUTEX_RECURSIVE;
-               pthread_mutex_init (&mutex->mutex, NULL);
-               pthread_cond_init (&mutex->cond, NULL);
+               ret = pthread_mutex_init (&mutex->mutex, NULL);
+               thr_ret = pthread_cond_init (&mutex->cond, NULL);
+               g_assert (thr_ret == 0);
        }
        
-       return 0;
+       return(ret);
 }
 
 int
@@ -195,7 +208,7 @@ mono_mutex_lock (mono_mutex_t *mutex)
                                break;
                        } else {
                                mutex->waiters++;
-                               if (pthread_cond_wait (&mutex->cond, &mutex->mutex) == -1)
+                               if (pthread_cond_wait (&mutex->cond, &mutex->mutex) != 0)
                                        return EINVAL;
                                mutex->waiters--;
                        }
@@ -282,6 +295,8 @@ mono_mutex_timedlock (mono_mutex_t *mutex, const struct timespec *timeout)
 int
 mono_mutex_unlock (mono_mutex_t *mutex)
 {
+       int thr_ret;
+       
        switch (mutex->type) {
        case MONO_MUTEX_NORMAL:
                return pthread_mutex_unlock (&mutex->mutex);
@@ -294,8 +309,10 @@ mono_mutex_unlock (mono_mutex_t *mutex)
                mutex->depth--;
                if (mutex->depth == 0) {
                        mutex->owner = MONO_THREAD_NONE;
-                       if (mutex->waiters > 0)
-                               pthread_cond_signal (&mutex->cond);
+                       if (mutex->waiters > 0) {
+                               thr_ret = pthread_cond_signal (&mutex->cond);
+                               g_assert (thr_ret == 0);
+                       }
                }
                
                return pthread_mutex_unlock (&mutex->mutex);
@@ -308,6 +325,7 @@ int
 mono_mutex_destroy (mono_mutex_t *mutex)
 {
        int ret = 0;
+       int thr_ret;
        
        switch (mutex->type) {
        case MONO_MUTEX_NORMAL:
@@ -315,7 +333,8 @@ mono_mutex_destroy (mono_mutex_t *mutex)
                break;
        case MONO_MUTEX_RECURSIVE:
                if ((ret = pthread_mutex_destroy (&mutex->mutex)) == 0) {
-                       pthread_cond_destroy (&mutex->cond);
+                       thr_ret = pthread_cond_destroy (&mutex->cond);
+                       g_assert (thr_ret == 0);
                }
        }
        
index b23cb97bd8cc3464130ae1f615a38bc4ee36c5c1..3c4ba577fff5c2255c574820fe09d81349a975dc 100644 (file)
@@ -159,6 +159,14 @@ typedef pthread_mutexattr_t mono_mutexattr_t;
 
 #endif /* USE_MONO_MUTEX */
 
+/* This is a function so it can be passed to pthread_cleanup_push -
+ * that is a macro and giving it a macro as a parameter breaks.
+ */
+static inline int mono_mutex_unlock_in_cleanup (mono_mutex_t *mutex)
+{
+       return(mono_mutex_unlock (mutex));
+}
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
index ec691838db221d2453986de11fb78626d8f93b08..3e908c11b7c5047e9ca1e1b05f956e3513a2d1b4 100644 (file)
@@ -174,15 +174,21 @@ gpointer CreateMutex(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean ow
        gpointer handle;
        gboolean ok;
        gchar *utf8_name;
+       int thr_ret;
+       gpointer ret = NULL;
        
        mono_once (&mutex_ops_once, mutex_ops_init);
 
+       /* w32 seems to guarantee that opening named mutexes can't
+        * race each other
+        */
+       pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
+                             (void *)&named_mutex_mutex);
+       thr_ret = mono_mutex_lock (&named_mutex_mutex);
+       g_assert (thr_ret == 0);
+
        if(name!=NULL) {
                utf8_name=g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
-               /* w32 seems to guarantee that opening named mutexes can't
-                * race each other
-                */
-               mono_mutex_lock (&named_mutex_mutex);
        } else {
                utf8_name=NULL;
        }
@@ -201,14 +207,13 @@ gpointer CreateMutex(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean ow
                         * object.
                         */
                        g_free (utf8_name);
-                       mono_mutex_unlock (&named_mutex_mutex);
                        SetLastError (ERROR_INVALID_HANDLE);
-                       return(NULL);
+                       goto cleanup;
                } else if (handle!=NULL) {
                        g_free (utf8_name);
-                       mono_mutex_unlock (&named_mutex_mutex);
                        _wapi_handle_ref (handle);
-                       return(handle);
+                       ret = handle;
+                       goto cleanup;
                }
                /* Otherwise fall through to create the mutex. */
        }
@@ -220,14 +225,13 @@ gpointer CreateMutex(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean ow
                if(utf8_name!=NULL) {
                        g_free (utf8_name);
                }
-               if(name!=NULL) {
-                       mono_mutex_unlock (&named_mutex_mutex);
-               }
-               
-               return(NULL);
+               goto cleanup;
        }
 
-       _wapi_handle_lock_handle (handle);
+       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+                             handle);
+       thr_ret = _wapi_handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
                                (gpointer *)&mutex_handle, NULL);
@@ -238,14 +242,10 @@ gpointer CreateMutex(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean ow
                        g_free (utf8_name);
                }
                
-               if(name!=NULL) {
-                       mono_mutex_unlock (&named_mutex_mutex);
-               }
-               
-               _wapi_handle_unlock_handle (handle);
-               return(NULL);
+               goto handle_cleanup;
        }
-
+       ret = handle;
+       
        if(utf8_name!=NULL) {
                mutex_handle->sharedns.name=_wapi_handle_scratch_store (
                        utf8_name, strlen (utf8_name));
@@ -262,17 +262,21 @@ gpointer CreateMutex(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean ow
                   handle);
 #endif
 
-       _wapi_handle_unlock_handle (handle);
-
        if(utf8_name!=NULL) {
                g_free (utf8_name);
        }
+
+handle_cleanup:
+       thr_ret = _wapi_handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
        
-       if(name!=NULL) {
-               mono_mutex_unlock (&named_mutex_mutex);
-       }
-               
-       return(handle);
+cleanup:
+       thr_ret = mono_mutex_unlock (&named_mutex_mutex);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
+       
+       return(ret);
 }
 
 /**
@@ -290,6 +294,8 @@ gboolean ReleaseMutex(gpointer handle)
        gboolean ok;
        pthread_t tid=pthread_self();
        pid_t pid=getpid ();
+       int thr_ret;
+       gboolean ret = FALSE;
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
                                (gpointer *)&mutex_handle, NULL);
@@ -299,7 +305,10 @@ gboolean ReleaseMutex(gpointer handle)
                return(FALSE);
        }
 
-       _wapi_handle_lock_handle (handle);
+       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+                             handle);
+       thr_ret = _wapi_handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
        
 #ifdef DEBUG
        g_message(G_GNUC_PRETTY_FUNCTION ": Releasing mutex handle %p",
@@ -311,10 +320,10 @@ gboolean ReleaseMutex(gpointer handle)
                g_message(G_GNUC_PRETTY_FUNCTION ": We don't own mutex handle %p (owned by %d:%ld, me %d:%ld)", handle, mutex_handle->pid, mutex_handle->tid, pid, tid);
 #endif
 
-               _wapi_handle_unlock_handle (handle);
-               return(FALSE);
+               goto cleanup;
        }
-
+       ret = TRUE;
+       
        /* OK, we own this mutex */
        mutex_handle->recursion--;
        
@@ -329,7 +338,10 @@ gboolean ReleaseMutex(gpointer handle)
                _wapi_handle_set_signal_state (handle, TRUE, FALSE);
        }
 
-       _wapi_handle_unlock_handle (handle);
+cleanup:
+       thr_ret = _wapi_handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
        
-       return(TRUE);
+       return(ret);
 }
index 047ff338a9a051208ed07c76c4251b826641a77d..4538064d168e9321bccf8dea1d10dd292524d283 100644 (file)
@@ -113,6 +113,8 @@ gpointer CreateSemaphore(WapiSecurityAttributes *security G_GNUC_UNUSED, gint32
        struct _WapiHandle_sem *sem_handle;
        gpointer handle;
        gboolean ok;
+       int thr_ret;
+       gpointer ret = NULL;
        
        mono_once (&sem_ops_once, sem_ops_init);
        
@@ -139,17 +141,20 @@ gpointer CreateSemaphore(WapiSecurityAttributes *security G_GNUC_UNUSED, gint32
                return(NULL);
        }
 
-       _wapi_handle_lock_handle (handle);
+       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+                             handle);
+       thr_ret = _wapi_handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_SEM,
                                (gpointer *)&sem_handle, NULL);
        if(ok==FALSE) {
                g_warning (G_GNUC_PRETTY_FUNCTION
                           ": error lookup up semaphore handle %p", handle);
-               _wapi_handle_unlock_handle (handle);
-               return(NULL);
+               goto cleanup;
        }
-
+       ret = handle;
+       
        sem_handle->val=initial;
        sem_handle->max=max;
 
@@ -163,9 +168,12 @@ gpointer CreateSemaphore(WapiSecurityAttributes *security G_GNUC_UNUSED, gint32
                  initial, max);
 #endif
 
-       _wapi_handle_unlock_handle (handle);
+cleanup:
+       thr_ret = _wapi_handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
        
-       return(handle);
+       return(ret);
 }
 
 /**
@@ -185,6 +193,7 @@ gboolean ReleaseSemaphore(gpointer handle, gint32 count, gint32 *prevcount)
        struct _WapiHandle_sem *sem_handle;
        gboolean ok;
        gboolean ret=FALSE;
+       int thr_ret;
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_SEM,
                                (gpointer *)&sem_handle, NULL);
@@ -194,7 +203,10 @@ gboolean ReleaseSemaphore(gpointer handle, gint32 count, gint32 *prevcount)
                return(FALSE);
        }
 
-       _wapi_handle_lock_handle (handle);
+       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+                             handle);
+       thr_ret = _wapi_handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
 
 #ifdef DEBUG
        g_message(G_GNUC_PRETTY_FUNCTION ": sem %p val %d count %d",
@@ -229,7 +241,9 @@ gboolean ReleaseSemaphore(gpointer handle, gint32 count, gint32 *prevcount)
 #endif
        
 end:
-       _wapi_handle_unlock_handle (handle);
+       thr_ret = _wapi_handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
 
        return(ret);
 }
index aa37a29265e0d06954bac0a0b2a2d74a7355c7e5..22713e3618e1787c76a4ad936a462443d5a2f6cd 100644 (file)
@@ -70,7 +70,7 @@
 guchar *_wapi_shm_file (_wapi_shm_t type, guint32 segment)
 {
        static guchar file[_POSIX_PATH_MAX];
-       guchar *name, *filename, *dir, *wapi_dir;
+       guchar *name = NULL, *filename, *dir, *wapi_dir;
        gchar machine_name[256];
 
        if (gethostname(machine_name, sizeof(machine_name)) != 0)
@@ -162,7 +162,7 @@ static int _wapi_shm_file_open (const guchar *filename, _wapi_shm_t type,
 {
        int fd;
        struct stat statbuf;
-       guint32 wanted_size;
+       guint32 wanted_size = 0;
        
        if(created) {
                *created=FALSE;
index b38d409dde7aa114057ba66d038bcf6429c7ca42..8bf842ac1e34a27d54be48f5faca7e1e9c863850 100644 (file)
@@ -162,13 +162,19 @@ int WSACleanup(void)
 
 static void error_init(void)
 {
-       pthread_key_create(&error_key, NULL);
+       int ret;
+       
+       ret = pthread_key_create(&error_key, NULL);
+       g_assert (ret == 0);
 }
 
 void WSASetLastError(int error)
 {
+       int ret;
+       
        mono_once(&error_key_once, error_init);
-       pthread_setspecific(error_key, GINT_TO_POINTER(error));
+       ret = pthread_setspecific(error_key, GINT_TO_POINTER(error));
+       g_assert (ret == 0);
 }
 
 int WSAGetLastError(void)
@@ -197,6 +203,8 @@ guint32 _wapi_accept(guint32 handle, struct sockaddr *addr,
        gpointer new_handle;
        gboolean ok;
        int fd;
+       int thr_ret;
+       guint32 ret = INVALID_SOCKET;
        
        if(startup_count==0) {
                WSASetLastError(WSANOTINITIALISED);
@@ -233,16 +241,19 @@ guint32 _wapi_accept(guint32 handle, struct sockaddr *addr,
                return(INVALID_SOCKET);
        }
 
-       _wapi_handle_lock_handle (new_handle);
+       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+                             new_handle);
+       thr_ret = _wapi_handle_lock_handle (new_handle);
+       g_assert (thr_ret == 0);
        
        ok=_wapi_lookup_handle (new_handle, WAPI_HANDLE_SOCKET, NULL,
                                (gpointer *)&new_socket_private_handle);
        if(ok==FALSE) {
                g_warning (G_GNUC_PRETTY_FUNCTION
                           ": error looking up socket handle 0x%x", handle);
-               _wapi_handle_unlock_handle (new_handle);
-               return(INVALID_SOCKET);
+               goto cleanup;
        }
+       ret = GPOINTER_TO_UINT (new_handle);
        
        new_socket_private_handle->fd=fd;
        
@@ -252,9 +263,12 @@ guint32 _wapi_accept(guint32 handle, struct sockaddr *addr,
                  new_handle, new_socket_private_handle->fd);
 #endif
 
-       _wapi_handle_unlock_handle (new_handle);
-
-       return(GPOINTER_TO_UINT (new_handle));
+cleanup:
+       thr_ret = _wapi_handle_unlock_handle (new_handle);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
+       
+       return(ret);
 }
 
 int _wapi_bind(guint32 handle, struct sockaddr *my_addr, socklen_t addrlen)
@@ -725,6 +739,8 @@ guint32 _wapi_socket(int domain, int type, int protocol)
        gpointer handle;
        gboolean ok;
        int fd;
+       int thr_ret;
+       guint32 ret = INVALID_SOCKET;
        
        fd=socket(domain, type, protocol);
        if (fd==-1 && domain == AF_INET && type == SOCK_RAW && protocol == 0) {
@@ -752,16 +768,19 @@ guint32 _wapi_socket(int domain, int type, int protocol)
                return(INVALID_SOCKET);
        }
 
-       _wapi_handle_lock_handle (handle);
+       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+                             handle);
+       thr_ret = _wapi_handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET, NULL,
                                (gpointer *)&socket_private_handle);
        if(ok==FALSE) {
                g_warning (G_GNUC_PRETTY_FUNCTION
                           ": error looking up socket handle %p", handle);
-               _wapi_handle_unlock_handle (handle);
-               return(INVALID_SOCKET);
+               goto cleanup;
        }
+       ret = GPOINTER_TO_UINT (handle);
        
        socket_private_handle->fd=fd;
        
@@ -771,9 +790,12 @@ guint32 _wapi_socket(int domain, int type, int protocol)
                  socket_private_handle->fd);
 #endif
 
-       _wapi_handle_unlock_handle (handle);
-
-       return(GPOINTER_TO_UINT (handle));
+cleanup:
+       thr_ret = _wapi_handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
+       
+       return(ret);
 }
 
 struct hostent *_wapi_gethostbyname(const char *hostname)
index e8bda4e4e597957a01338cae80c9cdd2f486779f..533d6b0513b3445f3c7ba5216c820e1d423cab98 100644 (file)
@@ -15,7 +15,7 @@
 
 #include <mono/io-layer/timed-thread.h>
 
-extern const struct _WapiHandleOps _wapi_thread_ops;
+extern struct _WapiHandleOps _wapi_thread_ops;
 
 typedef enum {
        THREAD_STATE_START,
index d45d1db56307a22979a0fd6173be5f66dfc20d24..1b10dfd8ac172d43048fe8ffdbbfe7980c6de5b7 100644 (file)
@@ -31,7 +31,6 @@
 
 #undef DEBUG
 #undef TLS_DEBUG
-#undef TLS_PTHREAD_MUTEX
 
 
 /* Hash threads with tids. I thought of using TLS for this, but that
@@ -48,7 +47,7 @@ static MonoGHashTable *tls_gc_hash = NULL;
 static void thread_close_private (gpointer handle);
 static void thread_own (gpointer handle);
 
-const struct _WapiHandleOps _wapi_thread_ops = {
+struct _WapiHandleOps _wapi_thread_ops = {
        NULL,                           /* close_shared */
        thread_close_private,           /* close_private */
        NULL,                           /* signal */
@@ -124,6 +123,7 @@ static void thread_exit(guint32 exitstatus, gpointer handle)
        struct _WapiHandle_thread *thread_handle;
        struct _WapiHandlePrivate_thread *thread_private_handle;
        gboolean ok;
+       int thr_ret;
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
                                (gpointer *)&thread_handle,
@@ -134,7 +134,10 @@ static void thread_exit(guint32 exitstatus, gpointer handle)
                return;
        }
 
-       _wapi_handle_lock_handle (handle);
+       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+                             handle);
+       thr_ret = _wapi_handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
 
 #ifdef DEBUG
        g_message (G_GNUC_PRETTY_FUNCTION
@@ -145,7 +148,9 @@ static void thread_exit(guint32 exitstatus, gpointer handle)
        thread_handle->state=THREAD_STATE_EXITED;
        _wapi_handle_set_signal_state (handle, TRUE, TRUE);
 
-       _wapi_handle_unlock_handle (handle);
+       thr_ret = _wapi_handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
        
 #ifdef DEBUG
        g_message(G_GNUC_PRETTY_FUNCTION
@@ -154,9 +159,16 @@ static void thread_exit(guint32 exitstatus, gpointer handle)
 #endif
 
        /* Remove this thread from the hash */
-       mono_mutex_lock(&thread_hash_mutex);
+       pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
+                             (void *)&thread_hash_mutex);
+       thr_ret = mono_mutex_lock(&thread_hash_mutex);
+       g_assert (thr_ret == 0);
+       
        g_hash_table_remove(thread_hash, &thread_private_handle->thread->id);
-       mono_mutex_unlock(&thread_hash_mutex);
+
+       thr_ret = mono_mutex_unlock(&thread_hash_mutex);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
 
        /* The thread is no longer active, so unref it */
        _wapi_handle_unref (handle);
@@ -193,6 +205,9 @@ gpointer CreateThread(WapiSecurityAttributes *security G_GNUC_UNUSED, guint32 st
        gpointer handle;
        gboolean ok;
        int ret;
+       int thr_ret;
+       int i, unrefs = 0;
+       gpointer ct_ret = NULL;
        
        mono_once(&thread_hash_once, thread_hash_init);
        mono_once (&thread_ops_once, thread_ops_init);
@@ -208,7 +223,10 @@ gpointer CreateThread(WapiSecurityAttributes *security G_GNUC_UNUSED, guint32 st
                return(NULL);
        }
 
-       _wapi_handle_lock_handle (handle);
+       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+                             handle);
+       thr_ret = _wapi_handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
        
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
                                (gpointer *)&thread_handle,
@@ -216,8 +234,7 @@ gpointer CreateThread(WapiSecurityAttributes *security G_GNUC_UNUSED, guint32 st
        if(ok==FALSE) {
                g_warning (G_GNUC_PRETTY_FUNCTION
                           ": error looking up thread handle %p", handle);
-               _wapi_handle_unlock_handle (handle);
-               return(NULL);
+               goto cleanup;
        }
 
        /* Hold a reference while the thread is active, because we use
@@ -230,20 +247,26 @@ gpointer CreateThread(WapiSecurityAttributes *security G_GNUC_UNUSED, guint32 st
        /* Lock around the thread create, so that the new thread cant
         * race us to look up the thread handle in GetCurrentThread()
         */
-       mono_mutex_lock(&thread_hash_mutex);
+       pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
+                             (void *)&thread_hash_mutex);
+       thr_ret = mono_mutex_lock(&thread_hash_mutex);
+       g_assert (thr_ret == 0);
        
        /* Set a 2M stack size.  This is the default on Linux, but BSD
         * needs it.  (The original bug report from Martin Dvorak <md@9ll.cz>
         * set the size to 2M-4k.  I don't know why it's short by 4k, so
         * I'm leaving it as 2M until I'm told differently.)
         */
-       pthread_attr_init(&attr);
+       thr_ret = pthread_attr_init(&attr);
+       g_assert (thr_ret == 0);
+       
        /* defaults of 2Mb for 32bits and 4Mb for 64bits */
        if (stacksize == 0)
                stacksize = (SIZEOF_VOID_P / 2) * 1024 *1024;
 
 #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
-       pthread_attr_setstacksize(&attr, stacksize);
+       thr_ret = pthread_attr_setstacksize(&attr, stacksize);
+       g_assert (thr_ret == 0);
 #endif
 
        ret=_wapi_timed_thread_create(&thread_private_handle->thread, &attr,
@@ -254,18 +277,14 @@ gpointer CreateThread(WapiSecurityAttributes *security G_GNUC_UNUSED, guint32 st
                g_message(G_GNUC_PRETTY_FUNCTION ": Thread create error: %s",
                          strerror(ret));
 #endif
-               mono_mutex_unlock(&thread_hash_mutex);
-               _wapi_handle_unlock_handle (handle);
-               _wapi_handle_unref (handle);
-               
-               /* And again, because of the reference we took above */
-               _wapi_handle_unref (handle);
-               return(NULL);
+               /* Two, because of the reference we took above */
+               unrefs = 2;
+               goto thread_hash_cleanup;
        }
-
+       ct_ret = handle;
+       
        g_hash_table_insert(thread_hash, &thread_private_handle->thread->id,
                            handle);
-       mono_mutex_unlock(&thread_hash_mutex);
        
 #ifdef DEBUG
        g_message(G_GNUC_PRETTY_FUNCTION
@@ -282,14 +301,30 @@ gpointer CreateThread(WapiSecurityAttributes *security G_GNUC_UNUSED, guint32 st
 #endif
        }
 
-       _wapi_handle_unlock_handle (handle);
+thread_hash_cleanup:
+       thr_ret = mono_mutex_unlock (&thread_hash_mutex);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
+       
+cleanup:
+       thr_ret = _wapi_handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
        
-       return(handle);
+       /* Must not call _wapi_handle_unref() with the handle already
+        * locked
+        */
+       for (i = 0; i < unrefs; i++) {
+               _wapi_handle_unref (handle);
+       }
+
+       return(ct_ret);
 }
 
 gpointer OpenThread (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, guint32 tid)
 {
        gpointer ret=NULL;
+       int thr_ret;
        
        mono_once(&thread_hash_once, thread_hash_init);
        mono_once (&thread_ops_once, thread_ops_init);
@@ -298,10 +333,16 @@ gpointer OpenThread (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSE
        g_message (G_GNUC_PRETTY_FUNCTION ": looking up thread %d", tid);
 #endif
 
-       mono_mutex_lock(&thread_hash_mutex);
+       pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
+                             (void *)&thread_hash_mutex);
+       thr_ret = mono_mutex_lock(&thread_hash_mutex);
+       g_assert (thr_ret == 0);
        
        ret=g_hash_table_lookup(thread_hash, &tid);
-       mono_mutex_unlock(&thread_hash_mutex);
+
+       thr_ret = mono_mutex_unlock(&thread_hash_mutex);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
        
        if(ret!=NULL) {
                _wapi_handle_ref (ret);
@@ -408,7 +449,10 @@ static gpointer thread_attach(guint32 *tid)
        gpointer handle;
        gboolean ok;
        int ret;
-
+       int thr_ret;
+       int i, unrefs = 0;
+       gpointer ta_ret = NULL;
+       
        mono_once(&thread_hash_once, thread_hash_init);
        mono_once (&thread_ops_once, thread_ops_init);
 
@@ -419,7 +463,10 @@ static gpointer thread_attach(guint32 *tid)
                return(NULL);
        }
 
-       _wapi_handle_lock_handle (handle);
+       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+                             handle);
+       thr_ret = _wapi_handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
 
        ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
                                (gpointer *)&thread_handle,
@@ -427,8 +474,7 @@ static gpointer thread_attach(guint32 *tid)
        if(ok==FALSE) {
                g_warning (G_GNUC_PRETTY_FUNCTION
                           ": error looking up thread handle %p", handle);
-               _wapi_handle_unlock_handle (handle);
-               return(NULL);
+               goto cleanup;
        }
 
        /* Hold a reference while the thread is active, because we use
@@ -441,7 +487,10 @@ static gpointer thread_attach(guint32 *tid)
        /* Lock around the thread create, so that the new thread cant
         * race us to look up the thread handle in GetCurrentThread()
         */
-       mono_mutex_lock(&thread_hash_mutex);
+       pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
+                             (void *)&thread_hash_mutex);
+       thr_ret = mono_mutex_lock(&thread_hash_mutex);
+       g_assert (thr_ret == 0);
 
        ret=_wapi_timed_thread_attach(&thread_private_handle->thread,
                                      thread_exit, handle);
@@ -450,18 +499,15 @@ static gpointer thread_attach(guint32 *tid)
                g_message(G_GNUC_PRETTY_FUNCTION ": Thread attach error: %s",
                          strerror(ret));
 #endif
-               mono_mutex_unlock(&thread_hash_mutex);
-               _wapi_handle_unlock_handle (handle);
-               _wapi_handle_unref (handle);
+               /* Two, because of the reference we took above */
+               unrefs = 2;
 
-               /* And again, because of the reference we took above */
-               _wapi_handle_unref (handle);
-               return(NULL);
+               goto thread_hash_cleanup;
        }
-
+       ta_ret = handle;
+       
        g_hash_table_insert(thread_hash, &thread_private_handle->thread->id,
                            handle);
-       mono_mutex_unlock(&thread_hash_mutex);
 
 #ifdef DEBUG
        g_message(G_GNUC_PRETTY_FUNCTION
@@ -478,9 +524,24 @@ static gpointer thread_attach(guint32 *tid)
 #endif
        }
 
-       _wapi_handle_unlock_handle (handle);
+thread_hash_cleanup:
+       thr_ret = mono_mutex_unlock (&thread_hash_mutex);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
+       
+cleanup:
+       thr_ret = _wapi_handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
 
-       return(handle);
+       /* Must not call _wapi_handle_unref() with the handle already
+        * locked
+        */
+       for (i = 0; i < unrefs; i++) {
+               _wapi_handle_unref (handle);
+       }
+       
+       return(ta_ret);
 }
 
 /**
@@ -498,16 +559,23 @@ gpointer GetCurrentThread(void)
 {
        gpointer ret=NULL;
        guint32 tid;
+       int thr_ret;
        
        mono_once(&thread_hash_once, thread_hash_init);
        mono_once (&thread_ops_once, thread_ops_init);
        
        tid=GetCurrentThreadId();
        
-       mono_mutex_lock(&thread_hash_mutex);
+       pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
+                             (void *)&thread_hash_mutex);
+       thr_ret = mono_mutex_lock(&thread_hash_mutex);
+       g_assert (thr_ret == 0);
 
        ret=g_hash_table_lookup(thread_hash, &tid);
-       mono_mutex_unlock(&thread_hash_mutex);
+
+       thr_ret = mono_mutex_unlock(&thread_hash_mutex);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
        
        if (!ret) {
                ret = thread_attach (NULL);
@@ -609,11 +677,7 @@ guint32 SuspendThread(gpointer handle)
 
 static pthread_key_t TLS_keys[TLS_MINIMUM_AVAILABLE];
 static gboolean TLS_used[TLS_MINIMUM_AVAILABLE]={FALSE};
-#ifdef TLS_PTHREAD_MUTEX
-static mono_mutex_t TLS_mutex=MONO_MUTEX_INITIALIZER;
-#else
 static guint32 TLS_spinlock=0;
-#endif
 
 /**
  * TlsAlloc:
@@ -628,23 +692,17 @@ static guint32 TLS_spinlock=0;
 guint32 TlsAlloc(void)
 {
        guint32 i;
+       int thr_ret;
        
-#ifdef TLS_PTHREAD_MUTEX
-       mono_mutex_lock(&TLS_mutex);
-#else
        MONO_SPIN_LOCK (TLS_spinlock);
-#endif
        
        for(i=0; i<TLS_MINIMUM_AVAILABLE; i++) {
                if(TLS_used[i]==FALSE) {
                        TLS_used[i]=TRUE;
-                       pthread_key_create(&TLS_keys[i], NULL);
+                       thr_ret = pthread_key_create(&TLS_keys[i], NULL);
+                       g_assert (thr_ret == 0);
 
-#ifdef TLS_PTHREAD_MUTEX
-                       mono_mutex_unlock(&TLS_mutex);
-#else
                        MONO_SPIN_UNLOCK (TLS_spinlock);
-#endif
        
 #ifdef TLS_DEBUG
                        g_message (G_GNUC_PRETTY_FUNCTION ": returning key %d",
@@ -655,11 +713,7 @@ guint32 TlsAlloc(void)
                }
        }
 
-#ifdef TLS_PTHREAD_MUTEX
-       mono_mutex_unlock(&TLS_mutex);
-#else
        MONO_SPIN_UNLOCK (TLS_spinlock);
-#endif
        
 #ifdef TLS_DEBUG
        g_message (G_GNUC_PRETTY_FUNCTION ": out of indices");
@@ -682,37 +736,29 @@ guint32 TlsAlloc(void)
  */
 gboolean TlsFree(guint32 idx)
 {
+       int thr_ret;
+       
 #ifdef TLS_DEBUG
        g_message (G_GNUC_PRETTY_FUNCTION ": freeing key %d", idx);
 #endif
 
-#ifdef TLS_PTHREAD_MUTEX
-       mono_mutex_lock(&TLS_mutex);
-#else
        MONO_SPIN_LOCK (TLS_spinlock);
-#endif
        
        if(TLS_used[idx]==FALSE) {
-#ifdef TLS_PTHREAD_MUTEX
-               mono_mutex_unlock(&TLS_mutex);
-#else
                MONO_SPIN_UNLOCK (TLS_spinlock);
-#endif
+
                return(FALSE);
        }
        
        TLS_used[idx]=FALSE;
-       pthread_key_delete(TLS_keys[idx]);
+       thr_ret = pthread_key_delete(TLS_keys[idx]);
+       g_assert (thr_ret == 0);
        
 #if HAVE_BOEHM_GC
        mono_g_hash_table_remove (tls_gc_hash, MAKE_GC_ID (idx));
 #endif
 
-#ifdef TLS_PTHREAD_MUTEX
-       mono_mutex_unlock(&TLS_mutex);
-#else
        MONO_SPIN_UNLOCK (TLS_spinlock);
-#endif
        
        return(TRUE);
 }
@@ -762,22 +808,15 @@ gboolean TlsSetValue(guint32 idx, gpointer value)
                   value);
 #endif
        
-#ifdef TLS_PTHREAD_MUTEX
-       mono_mutex_lock(&TLS_mutex);
-#else
        MONO_SPIN_LOCK (TLS_spinlock);
-#endif
        
        if(TLS_used[idx]==FALSE) {
 #ifdef TLS_DEBUG
                g_message (G_GNUC_PRETTY_FUNCTION ": key %d unused", idx);
 #endif
 
-#ifdef TLS_PTHREAD_MUTEX
-               mono_mutex_unlock(&TLS_mutex);
-#else
                MONO_SPIN_UNLOCK (TLS_spinlock);
-#endif
+
                return(FALSE);
        }
        
@@ -788,11 +827,8 @@ gboolean TlsSetValue(guint32 idx, gpointer value)
                           ": pthread_setspecific error: %s", strerror (ret));
 #endif
 
-#ifdef TLS_PTHREAD_MUTEX
-               mono_mutex_unlock(&TLS_mutex);
-#else
                MONO_SPIN_UNLOCK (TLS_spinlock);
-#endif
+
                return(FALSE);
        }
        
@@ -802,11 +838,7 @@ gboolean TlsSetValue(guint32 idx, gpointer value)
        mono_g_hash_table_insert (tls_gc_hash, MAKE_GC_ID (idx), value);
 #endif
 
-#ifdef TLS_PTHREAD_MUTEX
-       mono_mutex_unlock(&TLS_mutex);
-#else
        MONO_SPIN_UNLOCK (TLS_spinlock);
-#endif
        
        return(TRUE);
 }
index edf3dbd4ce63208d77f82baf9eebd7b6601d111c..5dcc43ff1fe9f6c91fcb97ce80d29ca1789198de 100644 (file)
@@ -33,13 +33,17 @@ static mono_once_t timed_thread_once = MONO_ONCE_INIT;
 
 static void timed_thread_init(void)
 {
-       pthread_key_create(&timed_thread_key, NULL);
+       int thr_ret;
+       
+       thr_ret = pthread_key_create(&timed_thread_key, NULL);
+       g_assert (thr_ret == 0);
 }
 
 void _wapi_timed_thread_exit(guint32 exitstatus)
 {
        TimedThread *thread;
        void *specific;
+       int thr_ret;
        
        if((specific = pthread_getspecific(timed_thread_key)) == NULL) {
                /* Handle cases which won't happen with correct usage.
@@ -49,7 +53,10 @@ void _wapi_timed_thread_exit(guint32 exitstatus)
        
        thread=(TimedThread *)specific;
        
-       mono_mutex_lock(&thread->join_mutex);
+       pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
+                             (void *)&thread->join_mutex);
+       thr_ret = mono_mutex_lock(&thread->join_mutex);
+       g_assert (thr_ret == 0);
        
        /* Tell a joiner that we're exiting.
         */
@@ -66,8 +73,12 @@ void _wapi_timed_thread_exit(guint32 exitstatus)
                thread->exit_routine(exitstatus, thread->exit_userdata);
        }
        
-       pthread_cond_signal(&thread->exit_cond);
-       mono_mutex_unlock(&thread->join_mutex);
+       thr_ret = pthread_cond_signal(&thread->exit_cond);
+       g_assert (thr_ret == 0);
+       
+       thr_ret = mono_mutex_unlock(&thread->join_mutex);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
        
        /* Call pthread_exit() to call destructors and really exit the
         * thread.
@@ -82,9 +93,11 @@ static void *timed_thread_start_routine(gpointer args) G_GNUC_NORETURN;
 static void *timed_thread_start_routine(gpointer args)
 {
        TimedThread *thread = (TimedThread *)args;
+       int thr_ret;
        
        mono_once(&timed_thread_once, timed_thread_init);
-       pthread_setspecific(timed_thread_key, (void *)thread);
+       thr_ret = pthread_setspecific(timed_thread_key, (void *)thread);
+       g_assert (thr_ret == 0);
 
        /* This used to be pthread_detach(thread->id);
         *
@@ -105,7 +118,8 @@ static void *timed_thread_start_routine(gpointer args)
         * This was 100% reproducible on Debian Woody with gcc 2.95.4,
         * and on Red Hat 9 with gcc 3.2.2.
         */
-       pthread_detach(pthread_self ());
+       thr_ret = pthread_detach(pthread_self ());
+       g_assert (thr_ret == 0);
 
        if(thread->create_flags & CREATE_SUSPENDED) {
                thread->suspend_count = 1;
@@ -126,11 +140,16 @@ int _wapi_timed_thread_create(TimedThread **threadp,
 {
        TimedThread *thread;
        int result;
+       int thr_ret;
        
        thread=(TimedThread *)g_new0(TimedThread, 1);
        
-       mono_mutex_init(&thread->join_mutex, NULL);
-       pthread_cond_init(&thread->exit_cond, NULL);
+       thr_ret = mono_mutex_init(&thread->join_mutex, NULL);
+       g_assert (thr_ret == 0);
+       
+       thr_ret = pthread_cond_init(&thread->exit_cond, NULL);
+       g_assert (thr_ret == 0);
+       
        thread->create_flags = create_flags;
        MONO_SEM_INIT (&thread->suspend_sem, 0);
        MONO_SEM_INIT (&thread->suspended_sem, 0);
@@ -158,13 +177,22 @@ int _wapi_timed_thread_attach(TimedThread **threadp,
                              gpointer exit_userdata)
 {
        TimedThread *thread;
-
+       int thr_ret;
+       
        thread=(TimedThread *)g_new0(TimedThread, 1);
 
-       mono_mutex_init(&thread->join_mutex, NULL);
-       pthread_cond_init(&thread->exit_cond, NULL);
-       sem_init (&thread->suspend_sem, 0, 0);
-       sem_init (&thread->suspended_sem, 0, 0);
+       thr_ret = mono_mutex_init(&thread->join_mutex, NULL);
+       g_assert (thr_ret == 0);
+       
+       thr_ret = pthread_cond_init(&thread->exit_cond, NULL);
+       g_assert (thr_ret == 0);
+       
+       thr_ret = sem_init (&thread->suspend_sem, 0, 0);
+       g_assert (thr_ret != -1);
+       
+       thr_ret = sem_init (&thread->suspended_sem, 0, 0);
+       g_assert (thr_ret != -1);
+       
        thread->exit_routine = exit_routine;
        thread->exit_userdata = exit_userdata;
        thread->exitstatus = 0;
@@ -176,7 +204,8 @@ int _wapi_timed_thread_attach(TimedThread **threadp,
         * called)
         */
        mono_once(&timed_thread_once, timed_thread_init);
-       pthread_setspecific(timed_thread_key, (void *)thread);
+       thr_ret = pthread_setspecific(timed_thread_key, (void *)thread);
+       g_assert (thr_ret == 0);
 
        *threadp = thread;
 
@@ -187,8 +216,13 @@ int _wapi_timed_thread_join(TimedThread *thread, struct timespec *timeout,
                            guint32 *exitstatus)
 {
        int result;
+       int thr_ret;
+       
+       pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
+                             (void *)&thread->join_mutex);
+       thr_ret = mono_mutex_lock(&thread->join_mutex);
+       g_assert (thr_ret == 0);
        
-       mono_mutex_lock(&thread->join_mutex);
        result=0;
        
        /* Wait until the thread announces that it's exiting, or until
@@ -205,7 +239,10 @@ int _wapi_timed_thread_join(TimedThread *thread, struct timespec *timeout,
                }
        }
        
-       mono_mutex_unlock(&thread->join_mutex);
+       thr_ret = mono_mutex_unlock(&thread->join_mutex);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
+       
        if(result == 0 && thread->exiting) {
                if(exitstatus!=NULL) {
                        *exitstatus = thread->exitstatus;
index 0369bd1d635b6de17e45eb8de60894ace83cb9f5..c579e94bc0b2b980eda9c70004df4b964325eecc 100644 (file)
@@ -44,6 +44,7 @@ guint32 WaitForSingleObject(gpointer handle, guint32 timeout)
 {
        guint32 ret, waited;
        struct timespec abstime;
+       int thr_ret;
        
        if(_wapi_handle_test_capabilities (handle,
                                           WAPI_HANDLE_CAP_WAIT)==FALSE) {
@@ -59,7 +60,10 @@ guint32 WaitForSingleObject(gpointer handle, guint32 timeout)
        g_message (G_GNUC_PRETTY_FUNCTION ": locking handle %p", handle);
 #endif
 
-       _wapi_handle_lock_handle (handle);
+       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+                             handle);
+       thr_ret = _wapi_handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
 
        if(_wapi_handle_test_capabilities (handle,
                                           WAPI_HANDLE_CAP_OWN)==TRUE) {
@@ -132,7 +136,10 @@ done:
        g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handle %p", handle);
 #endif
        
-       _wapi_handle_unlock_handle (handle);
+       thr_ret = _wapi_handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
+       
        return(ret);
 }
 
@@ -176,6 +183,7 @@ guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait,
 {
        guint32 ret, waited;
        struct timespec abstime;
+       int thr_ret;
        
        if(_wapi_handle_test_capabilities (signal_handle,
                                           WAPI_HANDLE_CAP_SIGNAL)==FALSE) {
@@ -191,7 +199,10 @@ guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait,
        g_message (G_GNUC_PRETTY_FUNCTION ": locking handle %p", wait);
 #endif
 
-       _wapi_handle_lock_handle (wait);
+       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+                             wait);
+       thr_ret = _wapi_handle_lock_handle (wait);
+       g_assert (thr_ret == 0);
 
        _wapi_handle_ops_signal (signal_handle);
 
@@ -265,7 +276,9 @@ done:
        g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handle %p", wait);
 #endif
 
-       _wapi_handle_unlock_handle (wait);
+       thr_ret = _wapi_handle_unlock_handle (wait);
+       g_assert (thr_ret == 0);
+       pthread_cleanup_pop (0);
 
        if(alertable==TRUE) {
                /* Deal with queued APC or IO completion routines */
@@ -274,6 +287,54 @@ done:
        return(ret);
 }
 
+struct handle_cleanup_data
+{
+       guint32 numobjects;
+       gpointer *handles;
+};
+
+static void handle_cleanup (void *data)
+{
+       struct handle_cleanup_data *handles = (struct handle_cleanup_data *)data;
+
+       _wapi_handle_unlock_handles (handles->numobjects, handles->handles);
+}
+
+static gboolean test_and_own (guint32 numobjects, gpointer *handles,
+                             gboolean waitall, guint32 *count,
+                             guint32 *lowest)
+{
+       struct handle_cleanup_data cleanup_data;
+       gboolean done;
+       int i;
+       
+#ifdef DEBUG
+       g_message (G_GNUC_PRETTY_FUNCTION ": locking handles");
+#endif
+       cleanup_data.numobjects = numobjects;
+       cleanup_data.handles = handles;
+       
+       pthread_cleanup_push (handle_cleanup, (void *)&cleanup_data);
+       done = _wapi_handle_count_signalled_handles (numobjects, handles,
+                                                    waitall, count, lowest);
+       if (done == TRUE) {
+               for (i = 0; i < numobjects; i++) {
+                       _wapi_handle_ops_own (handles[i]);
+               }
+       }
+       
+#ifdef DEBUG
+       g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handles");
+#endif
+
+       /* calls the unlock function */
+       pthread_cleanup_pop (1);
+
+       return(done);
+}
+
+
+
 /**
  * WaitForMultipleObjects:
  * @numobjects: The number of objects in @handles. The maximum allowed
@@ -311,6 +372,7 @@ guint32 WaitForMultipleObjects(guint32 numobjects, gpointer *handles,
        struct timespec abstime;
        guint i;
        guint32 ret;
+       int thr_ret;
        
        if(numobjects>MAXIMUM_WAIT_OBJECTS) {
 #ifdef DEBUG
@@ -371,34 +433,14 @@ guint32 WaitForMultipleObjects(guint32 numobjects, gpointer *handles,
                return(WAIT_FAILED);
        }
 
-#ifdef DEBUG
-       g_message (G_GNUC_PRETTY_FUNCTION ": locking handles");
-#endif
-
-       done=_wapi_handle_count_signalled_handles (numobjects, handles,
-                                                  waitall, &count, &lowest);
+       done=test_and_own (numobjects, handles, waitall, &count, &lowest);
        if(done==TRUE) {
-               for(i=0; i<numobjects; i++) {
-                       _wapi_handle_ops_own (handles[i]);
-               }
-               
-#ifdef DEBUG
-               g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handles");
-#endif
-
-               _wapi_handle_unlock_handles (numobjects, handles);
                return(WAIT_OBJECT_0+lowest);
        }
        
        /* Have to wait for some or all handles to become signalled
         */
 
-#ifdef DEBUG
-       g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handles");
-#endif
-
-       _wapi_handle_unlock_handles (numobjects, handles);
-
        if(timeout!=INFINITE) {
                _wapi_calc_timeout (&abstime, timeout);
        }
@@ -408,8 +450,10 @@ guint32 WaitForMultipleObjects(guint32 numobjects, gpointer *handles,
                g_message (G_GNUC_PRETTY_FUNCTION ": locking signal mutex");
 #endif
 
-               _wapi_handle_lock_signal_mutex ();
-
+               pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_signal_mutex, NULL);
+               thr_ret = _wapi_handle_lock_signal_mutex ();
+               g_assert (thr_ret == 0);
+               
                if(timeout==INFINITE) {
                        ret=_wapi_handle_wait_signal ();
                } else {
@@ -420,35 +464,17 @@ guint32 WaitForMultipleObjects(guint32 numobjects, gpointer *handles,
                g_message (G_GNUC_PRETTY_FUNCTION ": unlocking signal mutex");
 #endif
 
-               _wapi_handle_unlock_signal_mutex ();
+               thr_ret = _wapi_handle_unlock_signal_mutex (NULL);
+               g_assert (thr_ret == 0);
+               pthread_cleanup_pop (0);
                
                if(ret==0) {
                        /* Something was signalled ... */
-                       done=_wapi_handle_count_signalled_handles (numobjects,
-                                                                  handles,
-                                                                  waitall,
-                                                                  &count,
-                                                                  &lowest);
+                       done = test_and_own (numobjects, handles, waitall,
+                                            &count, &lowest);
                        if(done==TRUE) {
-                               for(i=0; i<numobjects; i++) {
-                                       _wapi_handle_ops_own (handles[i]);
-                               }
-
-#ifdef DEBUG
-                               g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handles");
-#endif
-
-                               _wapi_handle_unlock_handles (numobjects,
-                                                            handles);
-
                                return(WAIT_OBJECT_0+lowest);
                        }
-
-#ifdef DEBUG
-                       g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handles");
-#endif
-
-                       _wapi_handle_unlock_handles (numobjects, handles);
                } else {
                        /* Timeout or other error */
 #ifdef DEBUG