Bug in thread local storage ?
Francois Tigeot
ftigeot at wolfpond.org
Sun Jan 30 13:00:27 PST 2011
Hi all,
I've recently upgraded some mail servers to DragonFly-2.8 (from 2.6).
Since the upgrade, mail/milter-greylist has begun crashing.
I have been slowly pinpointing the root cause of the crashes with the
author of milter-greylist; they are caused by a Thread Local Storage
behavior specific to DragonFly 2.8+
The attached program has been written by Emmanuel Dreyfus, the author of
milter-greylist.
DragonFly 2.6.x gives these sort of results:
$ ./tss
parent (672727152) TSS key 0x0 set to 0xbfbffbc8
parent (672727152) TSS key 0x0 read as 0xbfbffbc8
child (672727376) starts, key = 0x0
tss: pthread_getspecific() failed in child
As do most other systems:
http://tech.groups.yahoo.com/group/milter-greylist/message/5727
The results are different on DragonFly 2.8 and 2.9:
$ ./tss
parent (5505216) TSS key 0x0 set to 0x7ffffffff310
parent (5505216) TSS key 0x0 read as 0x7ffffffff310
child (5505568) starts, key = 0x0
child (5505568) TSS key 0x0 read as 0x800533900
child (5505568) exit
parent (5505216) exit
The child is able to get a result with a storage key created by the
parent. I am no Thread Specific Storage specialist, but isn't this a bug ?
--
Francois Tigeot
/* cc -Wall -Werror -ansi -lpthread -o tss tss.c */
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <err.h>
#include <sysexits.h>
pthread_key_t key;
void *
child(arg)
void *arg;
{
void *tss;
printf("child (%d) starts, key = %p\n",
(int)pthread_self(), (void *)key);
if ((tss = pthread_getspecific(key)) == NULL)
errx(EX_OSERR, "pthread_getspecific() failed in child");
printf("child (%d) TSS key %p read as %p\n",
(int)pthread_self(), (void *)key, tss);
sleep(2);
printf("child (%d) exit\n", (int)pthread_self());
return NULL;
}
int
main(void) {
char test[] = "foo";
pthread_t tid;
void *tss;
if (pthread_key_create(&key, NULL) != 0)
err(EX_OSERR, "pthread_key_create() failed");
if (pthread_setspecific(key, test) != 0)
err(EX_OSERR, "pthread_setspecific() failed");
printf("parent (%d) TSS key %p set to %p\n",
(int)pthread_self(), (void *)key, test);
if (pthread_create(&tid, NULL, child, NULL) != 0)
err(EX_OSERR, "pthread_create() failed");
if ((tss = pthread_getspecific(key)) == NULL)
errx(EX_OSERR, "pthread_getspecific() failed in parent");
printf("parent (%d) TSS key %p read as %p\n",
(int)pthread_self(), (void *)key, tss);
sleep(3);
printf("parent (%d) exit\n", (int)pthread_self());
return 0;
}
More information about the Kernel
mailing list