Hi On Sun, 2 Mar 2003 12:31:49 -0500, Christopher Faylor wrote: > I don't see how a change which checks for a valid error condition > could be considered "wrong".
My apologies for not giving more details, I realize that last message was a little curt. There are two issues with the current CVS revision of dll_init.cc: - it is possible for the child to continue even though it has loaded a dll to the wrong address, with possible disastrous results (line 324, the return value of LoadLibrary is not checked); - the change does not address the problem I raised with unbalanced PROCESS_ATTACH and PROCESS_DETACH calls to the cygwin entry point function. The second issue is the one I want to pursue here. It is clear to me from reading the MDSN library docs combined with my own experiments that, on Win 9x/Me only, the sequence: h = LoadLibraryEx(d.name, NULL, DONT_RESOLVE_DLL_REFERENCES); FreeLibrary(h); always results in a call to DllMain() with PROCESS_DETACH even though there has been no corresponding call to DllMain() with PROCESS_ATTACH. This *may* cause a segv or data corruption, depending on what the DLL initialisation/finalisation code does. The only way to avoid this is to not use LoadLibraryEx(d.name, NULL, DONT_RESOLVE_DLL_REFERENCES) on WIn 9x/Me. I have also thought through the algorithm of this function some more, and have (hopefully) identified all the different failure conditions with appropriate actions. I have included the text of my proposed function here, so if anyone has time to read through it I would appreciate any constructive criticism. I have also attached a patch against the current CVS, so anyone using run-time loaded DLLS can check its behaviour on both 9x and NT. For me, this change gets the gnome desktop working for the first time on win ME. Regards, Steven void dll_list::load_after_fork (HANDLE parent, dll *first) { in_forkee = 1; dll d; void *next = first; while (next) { DWORD nb; /* Read the dll structure from the parent. */ if (!ReadProcessMemory (parent, next, &d, sizeof (dll), &nb) || nb != sizeof (dll)) return; /* We're only interested in dynamically loaded dlls. Hopefully, this function wouldn't even have been called unless the parent had some of those. */ if (d.type == DLL_LOAD) { HMODULE h; if (wincap.is_winnt()) { /* On NT/2K/XP we first test-load the DLL to see if if goes to the right address. We have to do this because if we load it fully and its at the wrong address then the later code that tries to adjust the load address fails. */ h = LoadLibraryEx (d.name, NULL, DONT_RESOLVE_DLL_REFERENCES); if (h == d.handle) { /* We got the right address first time. So now load it properly */ FreeLibrary(h); h = LoadLibrary(d.name); } } else { /* Win 9x/Me does not support the DONT_RESOLVE_DLL_REFERENCES flag, so we have to load the DLL straight up */ h = LoadLibrary (d.name); } if (h != d.handle) { /* We treat each error case differently */ if (h == NULL) { /* Some major failure. We cannot recover from this, so we bale out */ api_fatal ("child unable to load %s", d.name); } if (h > d.handle) { /* Loaded too high. We cannot fix this, so we bale out */ api_fatal ("unable to remap %s to same address as parent(%p) != %p", d.name, d.handle, h); } /* If the thread reaches here, then the DLL loaded too low. We can attempt to fix this by unloading it, reserving all free memory up to the address we want, then re-loading it and finally releasing the reserved memory. Sometimes this works, sometimes it dont. */ FreeLibrary (h); reserve_upto (d.name, (DWORD) d.handle); h = LoadLibrary(d.name); release_upto (d.name, (DWORD) d.handle); if (h != d.handle) { /* If its still the wrong address, then there's nothing more we can do. Bale out */ api_fatal ("unable to remap %s to same address as parent(%p) != %p", d.name, d.handle, h); } } } next = d.next; /* Get the address of the next DLL. */ } in_forkee = 0; }
dll_init.cc-patch
Description: Binary data
-- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Bug reporting: http://cygwin.com/bugs.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/