• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
A Bug in pthread_cond_destroy?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

A Bug in pthread_cond_destroy?


  • Subject: A Bug in pthread_cond_destroy?
  • From: "Kazuho Oku" <email@hidden>
  • Date: Wed, 9 Jan 2008 16:25:51 +0900

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:

This email sent to email@hidden

  • Follow-Ups:
    • Re: A Bug in pthread_cond_destroy?
      • From: Jim Magee <email@hidden>
  • Prev by Date: Re: fread/fwrite/fflush bug (Norm Green)
  • Next by Date: Re: A Bug in pthread_cond_destroy?
  • Previous by thread: Re: fread/fwrite/fflush bug (Norm Green)
  • Next by thread: Re: A Bug in pthread_cond_destroy?
  • Index(es):
    • Date
    • Thread