Mysterious segfaults when overriding pthread functions on glibc but not on musl

Viewed 323

I'm trying to override pthread_create and pthread_exit. The overrides should call the originals.

I can override pthread_create, and it appears to works as long as I exit my main thread with pthread_exit(0);. If I don't it segfaults.

If I even attempt to override pthread_exit, I get segfaults.

My setup is below:

#!/bin/sh

cat > test.c <<EOF
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

void *thr(void *Arg)
{
    printf("i=%d\n", (int)(intptr_t)Arg);
    return 0;
}
int main()
{
    putchar('\n');
    pthread_t tids[4];
    for(int i=0; i < sizeof tids / sizeof tids[0]; i++){
        pthread_create(tids+i, 0, thr, (void*)(intptr_t)i);

    }
    pthread_exit(0); //SEGFAULTS if this isn't here
    return 0;
}
EOF
cat > pthread_override.c <<EOF

#define _GNU_SOURCE
#include <dlfcn.h>
#include <pthread.h>
#include <stdio.h>

#if 1
__attribute__((__visibility__("default")))
int pthread_create(
        pthread_t *restrict Thr, 
        pthread_attr_t const *Attr,
        void *(*Fn) (void *), 
        void *Arg
        )
{
    int r;
    int (*real_pthread_create)(
        pthread_t *restrict Thr, 
        pthread_attr_t const *Attr,
        void *(*Fn) (void *), 
        void *Arg
    ) = dlsym(RTLD_NEXT, "pthread_create");
    printf("CREATE BEGIN: %p\n", (void*)Thr);
    r = real_pthread_create(Thr, Attr, Fn, Arg);
    printf("CREATE END: %p\n", (void*)Thr);
    return r;
}
#endif

#if 0 
//SEGFAULTS if this is allowed
__attribute__((__visibility__("default")))
_Noreturn
void pthread_exit(void *Retval)
{
    __attribute__((__noreturn__)) void (*real_pthread_exit)( void *Arg);
    real_pthread_exit = dlsym(RTLD_NEXT, "pthread_exit");
    printf("%p\n", (void*)real_pthread_exit);
    puts("EXIT");
    real_pthread_exit(Retval);
}
#endif
EOF

: ${CC:=gcc}
$CC -g -fpic pthread_override.c -shared -o pthread.so -ldl
$CC -g test.c $PWD/pthread.so -ldl -lpthread 
./a.out

Can anyone explain to me what I'm doing wrong and what the reason for the segfaults is?

The problems completely disappear if I substitute musl-gcc for gcc.

2 Answers
Related