summaryrefslogtreecommitdiff
path: root/sem_wait.c
diff options
context:
space:
mode:
Diffstat (limited to 'sem_wait.c')
-rw-r--r--sem_wait.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/sem_wait.c b/sem_wait.c
index 05d7326..d39d2b4 100644
--- a/sem_wait.c
+++ b/sem_wait.c
@@ -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;