diff options
Diffstat (limited to 'sem_wait.c')
-rw-r--r-- | sem_wait.c | 29 |
1 files changed, 23 insertions, 6 deletions
@@ -54,12 +54,13 @@ ptw32_sem_wait_cleanup(void * sem) if (pthread_mutex_lock (&s->lock) == 0) { /* + * If sema is destroyed do nothing, otherwise:- * If the sema is posted between us being cancelled and us locking * the sema again above then we need to consume that post but cancel * anyway. If we don't get the semaphore we indicate that we're no * longer waiting. */ - if (!(WaitForSingleObject(s->sem, 0) == WAIT_OBJECT_0)) + if (*((sem_t *)sem) != NULL && !(WaitForSingleObject(s->sem, 0) == WAIT_OBJECT_0)) { ++s->value; #ifdef NEED_SEM @@ -112,20 +113,28 @@ sem_wait (sem_t * sem) int result = 0; sem_t s = *sem; + pthread_testcancel(); + if (s == NULL) { result = EINVAL; } else { - - /* Faster to test before adjusting the count */ - pthread_testcancel(); - if ((result = pthread_mutex_lock (&s->lock)) == 0) { - int v = --s->value; + int v; + /* See sem_destroy.c + */ + if (*sem == NULL) + { + (void) pthread_mutex_unlock (&s->lock); + errno = EINVAL; + return -1; + } + + v = --s->value; (void) pthread_mutex_unlock (&s->lock); if (v < 0) @@ -136,6 +145,7 @@ sem_wait (sem_t * sem) /* Must wait */ pthread_cleanup_push(ptw32_sem_wait_cleanup, (void *) s); result = pthreadCancelableWait (s->sem); + /* Cleanup if we're canceled or on any other error */ pthread_cleanup_pop(result); #ifdef _MSC_VER #pragma inline_depth() @@ -145,6 +155,13 @@ sem_wait (sem_t * sem) if (!result && pthread_mutex_lock (&s->lock) == 0) { + if (*sem == NULL) + { + (void) pthread_mutex_unlock (&s->lock); + errno = EINVAL; + return -1; + } + if (s->leftToUnblock > 0) { --s->leftToUnblock; |