Search code examples
cmultithreadingtracedlopen

dlopen() in multithreaded application exit with "Trace/BPT trap"


I'm trying to load a framework at runtime in a Mac OS X application written in C using the following command:

dlopen("/System/Library/Frameworks/JavaVM.framework/JavaVM",RTLD_LAZY);

If I call dlopen() from the main thread it works as expected.

When I call it from another thread, the app exit with error: Trace/BPT trap

This is the code which calls dlopen() from the main thread (and works):

int main(int argc, char** argv)
{

    void *result = dlopen("/System/Library/Frameworks/JavaVM.framework/JavaVM",RTLD_LAZY);
    if (!result) {
        printf("can't open library JavaVM: %s\n", dlerror());
    }
    else {
        printf("library JavaVM loaded\n");
    }

    return 0;
}

The output is: library JavaVM loaded

This is the code which calls dlopen() from another thread (and exit during the call to that function):

void *loadJava(void* arg)
{
    void *result = dlopen("/System/Library/Frameworks/JavaVM.framework/JavaVM",RTLD_LAZY);
    if (!result) {
        printf("can't open library JavaVM: %s\n", dlerror());
    }
    else {
        printf("library JavaVM loaded\n");
    }
}

int main(int argc, char** argv)
{
    pthread_t vmthread;

    struct rlimit limit;
    size_t stack_size = 0;
    int rc = getrlimit(RLIMIT_STACK, &limit);
    if (rc == 0) {
        if (limit.rlim_cur != 0LL) {
            stack_size = (size_t)limit.rlim_cur;
        }
    }

    pthread_attr_t thread_attr;
    pthread_attr_init(&thread_attr);
    pthread_attr_setscope(&thread_attr, PTHREAD_SCOPE_SYSTEM);
    pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
    if (stack_size > 0) {
        pthread_attr_setstacksize(&thread_attr, stack_size);
    }

    pthread_create(&vmthread, &thread_attr, loadJava, NULL);
    pthread_attr_destroy(&thread_attr);

    pthread_exit(NULL);

    return 0;
}

The output is: Trace/BPT trap

Where is the mistake? Sorry if this is a stupid question but I'm still a newbie


Solution

  • It seems that dlopen() just isn't thread-safe, so you shouldn't call it under multiple threads.
    Or possibly, it isn't dlopen() which isn't thread-safe, but your library's initialization code that runs when it's loaded.

    There's no reason to call dlopen under threads, because it won't load the library multiple times.
    When you load the same file several times, then the second time does nothing (except incrementing some refcount), and just returns the same handle. So you gain nothing by loading it per thread.

    You can use dlmopen() to really load a library multiple times. But it's limited to 15 times.
    And even then, you should do it in main() before starting the threads (and give each thread its library handle), not from within the thread.