Mailing Lists: Apple Mailing Lists

Image of Mac OS face in stamp
 
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

A Bug in pthread_cond_destroy?



Hi,

If this is not the right place to report bugs of libc, please tell me
the right mailing list.  Thank you in advance, and sorry, if it is the
case.

I think I have found a bug in pthread_cond_destroy of Libc (with Mac
OS X 10.4.10).

Current implementation of pthread_cond_destroy does not check if
sigspending==0.  Thus if pthread_cond_destroy is called from a thread
other than that called pthread_cond_signal, the destructor may return
0 even if pthread_cond_signal is still in work (i.e. sigspending !=
0), leading to memory corruption or an infinite loop in
pthread_cond_signal.

For example, in the following code, thread B would sometimes read from
and/or write to freed memory.

Thread A:
    pthread_cond_wait(cond, &mutex);
    while ((err = pthread_cond_destroy(cond)) != 0) {
        assert(err == EBUSY);
        usleep(1);
    }
    free(cond);

Thread B:
    pthread_cond_signal(global_cond);

Note that the problem only arises when thread B does not lock the same
mutex as thread A when calling thread A (this is not a requirement in
POSIX threads).

Attached to this mail is a code that would reproduce this bug.  It
sends and receives pthread_cond_signals and increment a counter.
It compiled without any compile time defines, the program prints the
counter incrementing infinitely.
But if compiled with -DCLEAR_MEM -DSIGNAL_WO_LOCK it would suddenly
stop due to memory corruption.
Or if compiled with -DAPPLE_TEST -DSIGNAL_WO_LOCK it would check the
value of sispending and print an assertion failure.

To reproduce the bug with the attached code, a dual processor system
might be a requirement.

-- 
Kazuho Oku
#include <assert.h>
#include <mach/semaphore.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

#ifdef APPLE_TEST
typedef int32_t pthread_lock_t;
struct _pthread_mutex;
struct _pthread_cond
{
        long           sig;          /* Unique signature for this structure */
        pthread_lock_t lock;         /* Used for internal mutex on structure */
        semaphore_t    sem;          /* Kernel semaphore */
        struct _pthread_cond *next, *prev;  /* List of condition variables using
 mutex */
        struct _pthread_mutex *busy; /* mutex associated with variable */
        uint32_t       waiters:16,     /* Number of threads waiting */
                   sigspending:16;      /* Number of outstanding signals */
};
#endif

static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond_to_main = PTHREAD_COND_INITIALIZER;
static pthread_cond_t *cond_to_thread = NULL;

static void *my_thread(void *_1)
{
  pthread_cond_t t[16];
  int i;

#if APPLE_TEST
  assert(sizeof(struct _pthread_cond) == sizeof(pthread_cond_t));
#endif
  
  memset(t, 0x55, sizeof(t));
  for (i = 0; ; i = (i + 1) & 15) {
    assert(pthread_mutex_lock(&mutex) == 0);
    assert(pthread_cond_init(t + i, NULL) == 0);
    cond_to_thread = t + i;
    assert(pthread_cond_signal(&cond_to_main) == 0);
    assert(pthread_cond_wait(t + i, &mutex) == 0);
    assert(pthread_cond_destroy(t + i) == 0);
#ifdef APPLE_TEST
    assert(((struct _pthread_cond*)(t + i))->sigspending == 0);
#endif
    assert(pthread_mutex_unlock(&mutex) == 0);
#ifdef CLEAR_MEM
    memset(t + i, 0x55, sizeof(t[i]));
#endif
  }
  
  return NULL;
}

int main(int argc, char **argv)
{
  pthread_t tid;
  int i;
  
  assert(pthread_mutex_lock(&mutex) == 0);
  
  assert(pthread_create(&tid, NULL, my_thread, NULL) == 0);
  
  for (i = 0; ; i++) {
    pthread_cond_t *cc;
    while (cond_to_thread == NULL) {
      assert(pthread_cond_wait(&cond_to_main, &mutex) == 0);
    }
    cc = cond_to_thread;
    cond_to_thread = NULL;
#ifdef SIGNAL_WO_LOCK
    assert(pthread_mutex_unlock(&mutex) == 0);
#endif
    printf("%d\n", i);
    assert(pthread_cond_signal(cc) == 0);
#ifdef SIGNAL_WO_LOCK
    assert(pthread_mutex_lock(&mutex) == 0);
#endif
  }
  
  return 0;
}
 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/darwin-dev/email@hidden

This email sent to email@hidden



Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2007 Apple Inc. All rights reserved.