clone 435146 -1 reassign -1 libopenh323-1.18.0 1.18.0.dfsg-1 retitle -1 Segfault when dlclose()ing libopenh323 tags -1 -pending thanks
I've investigating this for hours and I've concluded to this: It seems that Asterisk's dynamic loader loads modules in two passes; modules with global symbols are loaded in the first pass while the rest of the modules (which can use these global symbols, hence the need for two passes) are loaded in the second. The information of whether a module contains global symbols or not is stored inside the module as a flag. Hence, the dynamic loader dlopen()s libraries with RTLD_LAZY | RTLD_LOCAL, checks the flags and: * if it is flagged global, it continues by promoting it to RTLD_GLOBAL, * if it is not, it calls dlclose(), pending loading in the second pass. chan_h323 is one of those that are not flagged that way; hence it is dlopen()ed/dlclose()d in the first pass and dlopen()ed another time in the second. Of course, when dlopening a shared library, all of its dependencies (e.g. libopenh323, libpt, libSDL etc. for chan_h323.so) are dynamically loaded too and on dlclose() they are also closed. It seems that Asterisk segfaults on the dlclose() of chan_h323.so which in turn is caused by unloading libopenh323. I wrote a very simple test suite that proves this and tested it with both 1.18 and 1.19[1]. Unfortunately the backtrace, as shown earlier in the bug report, is quite cryptic and C++ is not my area of expertise. It is worth noting however, that if RTLD_NOW is used instead of RTLD_LAZY (or the environment has LD_BIND_NOW, these two are equivalent) the bug does not occur. This is definitely a libopenh323 bug and Asterisk workarounds it by linking the main asterisk binary against libopenh323 and hence avoiding unloading it when its loader dlclose()s chan_h323.so. Regards, Faidon [1]: #include <stdio.h> #include <stdlib.h> #include <dlfcn.h> int main(int argc, char **argv) { void *handle; char *error; char *library; if (argc < 2) { fprintf(stderr, "Usage: %s foo.so\n", argv[0]); exit(EXIT_FAILURE); } library = argv[1]; handle = dlopen(library, RTLD_LAZY | RTLD_LOCAL); if (!handle) { fprintf(stderr, "%s\n", dlerror()); exit(EXIT_FAILURE); } dlerror(); /* Clear any existing error */ printf("loaded '%s', trying to unload...\n", library); /* unload dynamic library */ dlclose(handle); if ((error = dlerror()) != NULL) { fprintf(stderr, "%s\n", error); exit(EXIT_FAILURE); } printf("unloaded '%s', exiting...\n", library); exit(EXIT_SUCCESS); } -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]