diff --git a/winsup/CONTRIBUTORS b/winsup/CONTRIBUTORS index 84b4fa85f..635d8f5f4 100644 --- a/winsup/CONTRIBUTORS +++ b/winsup/CONTRIBUTORS @@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE. Individuals submitting their patches under 2-clause BSD: +David Allsopp David.Allsopp@cl.cam.ac.uk Erik M. Bray erik.bray@lri.fr ========================================================================= diff --git a/winsup/cygwin/dll_init.cc b/winsup/cygwin/dll_init.cc index 0fe5714ab..86776f2ce 100644 --- a/winsup/cygwin/dll_init.cc +++ b/winsup/cygwin/dll_init.cc @@ -271,9 +271,16 @@ void dll_list::populate_deps (dll* d) PIMAGE_DATA_DIRECTORY dd = pef->idata_dir (IMAGE_DIRECTORY_ENTRY_IMPORT); /* Annoyance: calling crealloc with a NULL pointer will use the wrong heap and crash, so we have to replicate some code */ - long maxdeps = 4; - d->deps = (dll**) cmalloc (HEAP_2_DLL, maxdeps*sizeof (dll*)); - d->ndeps = 0; + long maxdeps; + if (!d->ndeps) + { + maxdeps = 4; + d->deps = (dll**) cmalloc (HEAP_2_DLL, maxdeps*sizeof (dll*)); + } + else + { + maxdeps = d->ndeps; + } for (PIMAGE_IMPORT_DESCRIPTOR id= (PIMAGE_IMPORT_DESCRIPTOR) pef->rva (dd->VirtualAddress); dd->Size && id->Name; @@ -306,9 +313,45 @@ dll_list::topsort () /* make sure we have all the deps available */ dll* d = &start; + dll** dlopen_deps = NULL; + long maxdeps = 4; + long dlopen_ndeps = 0; + + if (loaded_dlls > 0) + dlopen_deps = (dll**) cmalloc (HEAP_2_DLL, maxdeps*sizeof (dll*)); + while ((d = d->next)) - if (!d->ndeps) - populate_deps (d); + { + if (!d->ndeps) + { + /* Ensure that all dlopen'd DLLs depend on previously dlopen'd DLLs. + This prevents topsort from reversing the order of dlopen'd DLLs on + calls to fork. */ + if (d->type == DLL_LOAD) + { + /* Initialise d->deps with all previously dlopen'd DLLs. */ + if (dlopen_ndeps) + { + d->ndeps = dlopen_ndeps; + d->deps = (dll**) cmalloc (HEAP_2_DLL, + dlopen_ndeps*sizeof (dll*)); + memcpy (d->deps, dlopen_deps, dlopen_ndeps*sizeof (dll*)); + } + /* Add this DLL to the list of previously dlopen'd DLLs. */ + if (dlopen_ndeps >= maxdeps) + { + maxdeps = 2*(1+maxdeps); + dlopen_deps = (dll**) crealloc (dlopen_deps, + maxdeps*sizeof (dll*)); + } + dlopen_deps[dlopen_ndeps++] = d; + } + populate_deps (d); + } + } + + if (loaded_dlls > 0) + cfree (dlopen_deps); /* unlink head and tail pointers so the sort can rebuild the list */ d = start.next; diff --git a/winsup/cygwin/release/2.7.1 b/winsup/cygwin/release/2.7.1 index 54e110050..411a0ae6b 100644 --- a/winsup/cygwin/release/2.7.1 +++ b/winsup/cygwin/release/2.7.1 @@ -8,6 +8,8 @@ What changed: - cygcheck and strace now always generate output with Unix LF line endings, rather than with DOS/Windows CR LF line endings. +- fork now preserves the load order of unrelated dlopen'd modules. + Bug Fixes ---------