Your message dated Fri, 18 May 2018 18:48:56 +0200 with message-id <[email protected]> and subject line Re: libstdc++ breaks dynamic unloading has caused the Debian Bug report #787734, regarding libstdc++ breaks dynamic unloading to be marked as done.
This means that you claim that the problem has been dealt with. If this is not the case it is now your responsibility to reopen the Bug report if necessary, and/or fix the problem forthwith. (NB: If you are a system administrator and have no idea what this message is talking about, this may indicate a serious mail system misconfiguration somewhere. Please contact [email protected] immediately.) -- 787734: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=787734 Debian Bug Tracking System Contact [email protected] with problems
--- Begin Message ---Package: libstdc++6 Version: 4.9.2-10 Severity: normal Where libstdc++ is dynamically loaded, in some cases it prevents an unrelated dynamic library that was loaded earlier from being unloaded. It also, incidentally, can't itself be unloaded, but that's much less of a problem. When I say that a library can't be unloaded, I mean that dlclose() indicates success, but the library actually remains mapped. I've been probing this with a test program, which just dlopens a sequence of libraries and then dlcloses them in reverse sequence, looking at what's actually mapped at each point: $ cat try_dl.c #include <stdio.h> #include <dlfcn.h> #include <unistd.h> #include <stdlib.h> int main(int argc, char **argv) { setbuf(stdout, NULL); if(argc <= 1) exit(2); argv++; argc--; void **handles = malloc(sizeof(void*) * argc); if(!handles) exit(1); char maps_cmd[100]; sprintf(maps_cmd, "sed -n 's:.* /: /:p' /proc/%ld/maps | sort -u", (long)getpid()); system(maps_cmd); for(int i = 0; i != argc; i++) { handles[i] = dlopen(argv[i], RTLD_LAZY); printf("dlopen(\"%s\", RTLD_LAZY) = %p\n", argv[i], handles[i]); system(maps_cmd); if(!handles[i]) exit(1); } for(int i = argc; i--; ) { int ret = dlclose(handles[i]); printf("dlclose(%p /*\"%s\"*/) = %d\n", handles[i], argv[i], ret); system(maps_cmd); if(ret) exit(1); } exit(0); } $ gcc -std=c99 try_dl.c -ldl -o try_dl $ ./try_dl /usr/lib/x86_64-linux-gnu/libperl.so.5.20 /usr/lib/x86_64-linux-gnu/libstdc++.so.6 /home/zefram/tmp/try_dl /lib/x86_64-linux-gnu/ld-2.19.so /lib/x86_64-linux-gnu/libc-2.19.so /lib/x86_64-linux-gnu/libdl-2.19.so dlopen("/usr/lib/x86_64-linux-gnu/libperl.so.5.20", RTLD_LAZY) = 0x1761070 /home/zefram/tmp/try_dl /lib/x86_64-linux-gnu/ld-2.19.so /lib/x86_64-linux-gnu/libc-2.19.so /lib/x86_64-linux-gnu/libcrypt-2.19.so /lib/x86_64-linux-gnu/libdl-2.19.so /lib/x86_64-linux-gnu/libm-2.19.so /lib/x86_64-linux-gnu/libpthread-2.19.so /usr/lib/x86_64-linux-gnu/libperl.so.5.20.2 dlopen("/usr/lib/x86_64-linux-gnu/libstdc++.so.6", RTLD_LAZY) = 0x1762ae0 /home/zefram/tmp/try_dl /lib/x86_64-linux-gnu/ld-2.19.so /lib/x86_64-linux-gnu/libc-2.19.so /lib/x86_64-linux-gnu/libcrypt-2.19.so /lib/x86_64-linux-gnu/libdl-2.19.so /lib/x86_64-linux-gnu/libgcc_s.so.1 /lib/x86_64-linux-gnu/libm-2.19.so /lib/x86_64-linux-gnu/libpthread-2.19.so /usr/lib/x86_64-linux-gnu/libperl.so.5.20.2 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.20 dlclose(0x1762ae0 /*"/usr/lib/x86_64-linux-gnu/libstdc++.so.6"*/) = 0 /home/zefram/tmp/try_dl /lib/x86_64-linux-gnu/ld-2.19.so /lib/x86_64-linux-gnu/libc-2.19.so /lib/x86_64-linux-gnu/libcrypt-2.19.so /lib/x86_64-linux-gnu/libdl-2.19.so /lib/x86_64-linux-gnu/libgcc_s.so.1 /lib/x86_64-linux-gnu/libm-2.19.so /lib/x86_64-linux-gnu/libpthread-2.19.so /usr/lib/x86_64-linux-gnu/libperl.so.5.20.2 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.20 dlclose(0x1761070 /*"/usr/lib/x86_64-linux-gnu/libperl.so.5.20"*/) = 0 /home/zefram/tmp/try_dl /lib/x86_64-linux-gnu/ld-2.19.so /lib/x86_64-linux-gnu/libc-2.19.so /lib/x86_64-linux-gnu/libcrypt-2.19.so /lib/x86_64-linux-gnu/libdl-2.19.so /lib/x86_64-linux-gnu/libgcc_s.so.1 /lib/x86_64-linux-gnu/libm-2.19.so /lib/x86_64-linux-gnu/libpthread-2.19.so /usr/lib/x86_64-linux-gnu/libperl.so.5.20.2 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.20 Observe that both libperl and libstdc++ remain loaded after the dlcloses, along with all their dependencies. But if libperl is loaded without libstdc++, it unloads as one would expect: $ ./try_dl /usr/lib/x86_64-linux-gnu/libperl.so.5.20 /home/zefram/tmp/try_dl /lib/x86_64-linux-gnu/ld-2.19.so /lib/x86_64-linux-gnu/libc-2.19.so /lib/x86_64-linux-gnu/libdl-2.19.so dlopen("/usr/lib/x86_64-linux-gnu/libperl.so.5.20", RTLD_LAZY) = 0xd48070 /home/zefram/tmp/try_dl /lib/x86_64-linux-gnu/ld-2.19.so /lib/x86_64-linux-gnu/libc-2.19.so /lib/x86_64-linux-gnu/libcrypt-2.19.so /lib/x86_64-linux-gnu/libdl-2.19.so /lib/x86_64-linux-gnu/libm-2.19.so /lib/x86_64-linux-gnu/libpthread-2.19.so /usr/lib/x86_64-linux-gnu/libperl.so.5.20.2 dlclose(0xd48070 /*"/usr/lib/x86_64-linux-gnu/libperl.so.5.20"*/) = 0 /home/zefram/tmp/try_dl /lib/x86_64-linux-gnu/ld-2.19.so /lib/x86_64-linux-gnu/libc-2.19.so /lib/x86_64-linux-gnu/libdl-2.19.so /lib/x86_64-linux-gnu/libpthread-2.19.so In this case libpthread, loaded as one of libperl's dependencies, won't unload, but this doesn't seem to be a problem. I'll spare you the full try_dl traces for other combinations; here's what I've learned from experimenting with it. Most shared libraries unload as they ought to. libpthread and libstdc++ share the unusual feature seen above that once loaded (either directly or as a dependency) they won't unload, and this seems to be something inherent in those libraries. A handful of other libraries also won't unload, but have either libpthread or libstdc++ as a dependency, so maybe their stickiness is caused by those two: for example librt (depending on libpthread) and libjack (depending on libstdc++). Not all libraries depending on those two get this behaviour, however. Sometimes, where a library depends on libstdc++ and others, the main library will unload, but libstdc++ and some other dependency will not. For example, libxatracker depends on libstdc++ and libffi (and some others), and can itself be unloaded along with some of its dependencies, but leaves both libstdc++ and libffi loaded. If libffi and libstdc++ are loaded without libxatracker, libstdc++ stays loaded but libffi unloads OK. libstdc++ alone, not libpthread, has this behaviour of keeping loaded a library that does not depend on it. Only a small number of libraries are affected by this: libperl (as seen above), libtcl, and libtk. The stickiness only occurs if libstdc++ is loaded after the victim. If libstdc++ is loaded first, then the victim is able to unload (though libstdc++ itself still won't unload). On a system I have access to with older packages, including libstdc++ 4.4.3, libstdc++ does not have the effect of preventing library unloading, either of itself or of other libraries. I do see libpthread and librt failing to unload, but not all of libpthread's dependents that have that behaviour on the newer system. The real problem that I run into due to this unloading problem is concerned with running Perl code under Apache, for which I have custom builds of both. Apache likes to process its configuration twice in each run, unloading all of its modules between runs. When mod_perl is shut down, it tries to unload everything that Perl loaded. It so happens that one of the Perl XS modules incorporates some C++ code and so brings in libstdc++ as a dependency. libperl, having been loaded as a dependency of mod_perl, ought to unload when Apache unloads mod_perl, but due to this problem with libstdc++ it does not. In the absence of unloading, the second time through the configuration has stale values in Perl global variables, and the process quickly crashes when Perl follows a hook pointing at a module that was successfully unloaded. I need libperl to unload properly in order to get a fresh set of its global variables. I have a potential workaround of modifying Apache to explicitly load libstdc++ during startup, because (as noted above) having it loaded first seems to prevent it interfering with the unloading of other modules. -zefram
--- End Message ---
--- Begin Message ---closing this issue, feedback requested in 2016, but no reply.
--- End Message ---

