Jakub Arnold
Jakub Arnold

Reputation: 87250

Reloading a dynamically loaded library with dlclose & dlopen works with Clang on Linux, but not with GCC

Consider the following loop

while (true) {
    void* lib = dlopen("bin/liblibrary.so", RTLD_NOW | RTLD_LOCAL);
    assert(lib);

    typedef void (*f_t)(void);

    f_t f = (f_t)dlsym(lib, "foo");
    assert(f);

    f();

    int res = dlclose(lib);
    assert(!res);
}

And a library that contains a simple function

extern "C" void foo() {
  printf("hello from foo\n");
}

This reloads the dynamic library on every iteration, or at least it should.

Compiling this on Linux (Arch) with clang 17.0.6 works as expected, and changing and recompiling the library makes the main binary run the new code.

But compiling with the same flags with GCC 14.1.1 does not work, and even when the library is reloaded it keeps calling the old code.

Compiling main with just clang++ main.cpp -o main and library with clang++ -shared -fPIC -o liblibrary.so library.cpp, and with GCC the same flags, except g++ instead of clang++.

edit: further testing, when I add an an __attribute__((destructor)) it does not get called with gCC, but it does get called with Clang, e.g.

__attribute__((constructor)) void init_library() {
    printf("Library loaded\n");
}

__attribute__((destructor)) void cleanup_library() {
    printf("Library unloaded\n");
}

Upvotes: 0

Views: 142

Answers (1)

Jakub Arnold
Jakub Arnold

Reputation: 87250

It seems the problem in this case was not actually in the example code, which was initially incorrect (using assert(!dlclose(lib))), but that was unfortunately only a problem in the example code and not in my actual code.

This did lead me down to another thread which hinted at --no-gnu-unique, which seems to be the flag that makes GCC actually unload the library.

Upvotes: 2

Related Questions