I'm working on a project that needs to arbitrarily load/unload Rust-based plugins (shared objects) into isolated dynamic library namespaces.
I use dlmopen(LM_ID_NEWLM, "rust-plugin.so", RTLD_LAZY)
to create a new namespace for a shared object. When the the shared object is no longer needed, I call dlclose()
.
Unfortunately, I've found that even when I dlclose()
so that only one shared object is valid at a time, after dlmopen()
ing 14 Rust plugin objects, I get the error:
dlmopen(rust-plugin.so) failed: /lib/x86_64-linux-gnu/libc.so.6: cannot allocate memory in static TLS block
Continued attempts to dlmopen()
after this failure result in a segmentation fault and no more namespaces available for dlmopen()
.
I seem to have isolated the problem to the libpthread.so
dependency of Rust shared objects. Other shared object dependencies like libgcc_s.so.1
(and any .so files I have tried, for that matter) can be opened and closed by the following code indefinitely, whereas libpthread.so
errors out after I open and close it 14 times.
#include <link.h>
#include <stdio.h>
#include <dlfcn.h>
#include <cstdlib>
void load(char const *file) {
void *handle_ = dlmopen(LM_ID_NEWLM, file, RTLD_LAZY);
if (!handle_) {
printf("dlmopen(%s) failed: %s\n", file, dlerror());
exit(1);
}
if (dlclose(handle_) != 0) {
exit(2);
}
}
int main() {
void *handle_;
for (int i = 0; true; i++) {
printf("%d\n", i);
load("libpthread.so.0");
}
}
Is there some way I can have libpthread properly clean up so I can avoid this issue?
dlclose()
an old plugin, Idlmopen()
a new plugin into the namespace that still containslibpthread.so.0
. – Deference