A Bug in pthread_cond_destroy?
site_archiver@lists.apple.com Delivered-To: darwin-dev@lists.apple.com Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from:to:subject:mime-version:content-type; bh=KkHaY3X1vTLif5gtWo7TatukUkOJ5t2oLd/je9vPRRU=; b=gcsc2sDwUk6jtFQOTec3zhyItemRISL4Z02fhoPPrtjMEiKy3364qX/EeIo91H1Tsnbll8clezGdkn+oaUb0qibHdAUog0P+Kcmgk39Jd+y7DrSl5hYVCNkrx9ckMKxKoRgUTcQlKpZVwnAPYI7UbpJdV6zbkJmAXWBgzp5KaDc= Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:to:subject:mime-version:content-type; b=mjsJbXrTB03E8UT0Y9yQmKPoXVWqdoAztWou3Qq3SJ+GehgBgYK5zzorHMLQ9stklzUu9cRpJD5pjf63DpOds7SrsqDhu7e7mM4UrHya+gq649IaiTDjZm68Rnth62LUEAqqxrpGReu9PocMa7WKvfmDhTid+QU+MhzNJFHzSwA= 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 (Darwin-dev@lists.apple.com) Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/darwin-dev/site_archiver%40lists.appl... This email sent to site_archiver@lists.apple.com
participants (1)
-
Kazuho Oku