On Sat, Jan 15, 2000 at 08:58:35PM -0500, Daniel Jacobowitz wrote: > Thus my confusion. On Linux, with a static libperl.a, there are no > multiple copies of libperl.so floating around to link to. The symbols > only exist in one place. Thus there is no choice about what symbols > link to. Still, I'm going to go over my linker logs again and see if > something useful turns up on that front. Ah-HA! I believe I see the problem. In fact, I'm almost sure I do. >From the one useful ltrace log I was able to get: % grep '^dl' min.ltrace.log dlopen("/usr/lib/apache/1.3/mod_cgi.so", 258) = 0x080a4198 dlsym(0x080a4198, "cgi_module") = 0x40187540 dlopen("/usr/lib/apache/1.3/mod_mime.so", 258) = 0x080a4518 dlsym(0x080a4518, "mime_module") = 0x40017a00 dlopen("/usr/lib/apache/1.3/mod_perl.so", 258) = 0x080a4850 dlsym(0x080a4850, "perl_module") = 0x402b6bc0 dlopen("/usr/lib/perl5/5.005/i386-linux/"..., 1) = 0x08118e60 dlsym(0x08118e60, "boot_DBI") = 0x402e4834 dlclose(0x080a4850) = 0 dlclose(0x080a4518) = 0 dlclose(0x080a4198) = 0 dlopen("/usr/lib/apache/1.3/mod_cgi.so", 258) = 0x0817f958 dlsym(0x0817f958, "cgi_module") = 0x40187540 dlopen("/usr/lib/apache/1.3/mod_mime.so", 258) = 0x080afcb8 dlsym(0x080afcb8, "mime_module") = 0x4018aa00 dlopen("/usr/lib/apache/1.3/mod_perl.so", 258) = 0x080a4170 dlsym(0x080a4170, "perl_module") = 0x402b9bc0 dlopen("/usr/lib/perl5/5.005/i386-linux/"..., 1) = 0x08118e60 dlsym(0x08118e60, "boot_DBI") = 0x402e4834 Notice that DBI is never dlclose()'d. But mod_perl is, when apache unloads its modules. The linker is not clever enough to realize that DBI depends on symbols in mod_perl.so. When mod_perl is reloaded at a DIFFERENT address, DBI has no reason to be rebound; its symbols are already resolved! But now they are resolved to the wrong places. This looks to be precisely contrary to the way that the linker is supposed to work, but I'll get back to that later. Thus my question is, is there a way to tell perl to dlclose() all modules? From looking through the perl code and seeing a noticeable lack of dlclose() calls, I'd say no. DynaLoader doesn't seem to support unloading things. It does, however, store the loaded dlopen handles in @DynaLoader::dl_librefs, which we could get at in a cleanup. Woah! This worked! Can I get opinions on the attached patch? Dan /--------------------------------\ /--------------------------------\ | Daniel Jacobowitz |__| SCS Class of 2002 | | Debian GNU/Linux Developer __ Carnegie Mellon University | | [EMAIL PROTECTED] | | [EMAIL PROTECTED] | \--------------------------------/ \--------------------------------/
--- mod_perl.c.orig Sat Jan 15 22:08:27 2000 +++ mod_perl.c Sat Jan 15 22:13:01 2000 @@ -417,23 +417,30 @@ #if MODULE_MAGIC_NUMBER >= MMN_130 static void mp_dso_unload(void *data) { - module *modp; - - if(!PERL_DSO_UNLOAD) - return; - - if(strEQ(top_module->name, "mod_perl.c")) - return; - - for(modp = top_module; modp; modp = modp->next) { - if(modp->dynamic_load_handle) { - MP_TRACE_g(fprintf(stderr, - "mod_perl: cancel dlclose for %s\n", - modp->name)); - modp->dynamic_load_handle = NULL; + I32 i; + void *handle; + AV *librefs; + SV *handle_sv; + + librefs = perl_get_av("DynaLoader::dl_librefs", FALSE); + if (!librefs) { + MP_TRACE(fprintf(stderr, "Could not get @dl_librefs for +unloading.\n")); + return; } - } -} + + for(i = 0; i <= AvFILL(librefs); i++) { + handle_sv = *av_fetch(librefs, i, FALSE); + if(!handle_sv) { + MP_TRACE(fprintf(stderr, "Could not fetch $dl_librefs[%d]!\n", +i)); + continue; + } + handle = (void *)SvIV(handle_sv); + if(dlclose(handle) < 0) { + fprintf(stderr, "Could not close $dl_librefs[%d]: %s\n", i, +dlerror()); + continue; + } + } +} #endif static void mp_server_notstarting(void *data)