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