Index: dll_init.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/dll_init.cc,v retrieving revision 1.36 diff -u -p -r1.36 dll_init.cc --- dll_init.cc 2 Mar 2003 18:37:17 -0000 1.36 +++ dll_init.cc 3 Mar 2003 17:45:22 -0000 @@ -287,7 +287,6 @@ void dll_list::load_after_fork (HANDLE parent, dll *first) { in_forkee = 1; - int try2 = 0; dll d; void *next = first; @@ -304,48 +303,61 @@ dll_list::load_after_fork (HANDLE parent the parent had some of those. */ if (d.type == DLL_LOAD) { - bool unload = true; - HMODULE h = LoadLibraryEx (d.name, NULL, DONT_RESOLVE_DLL_REFERENCES); - - if (!h) - system_printf ("can't reload %s", d.name); - /* See if DLL will load in proper place. If so, free it and reload - it the right way. - It sort of stinks that we can't invert the order of the FreeLibrary - and LoadLibrary since Microsoft documentation seems to imply that that - should do what we want. However, since the library was loaded above, - the second LoadLibrary does not execute it's startup code unless it - is first unloaded. */ - else if (h == d.handle) + HMODULE h; + if (wincap.is_winnt()) { - if (unload) - { - FreeLibrary (h); - LoadLibrary (d.name); - } + /* 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 if (try2) - api_fatal ("unable to remap %s to same address as parent(%p) != %p", - d.name, d.handle, h); else { - /* It loaded in the wrong place. Dunno why this happens but it always - seems to happen when there are multiple DLLs attempting to load into - the same address space. In the "forked" process, the second DLL always - loads into a different location. */ - FreeLibrary (h); - /* Block all of the memory up to the new load address. */ - reserve_upto (d.name, (DWORD) d.handle); - try2 = 1; /* And try */ - continue; /* again. */ - } - /* If we reached here, and try2 is set, then there is a lot of memory to - release. */ - if (try2) - { - release_upto (d.name, (DWORD) d.handle); - try2 = 0; + /* 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. */ }