diff options
-rw-r--r-- | winsup/cygwin/dll_init.cc | 26 | ||||
-rw-r--r-- | winsup/cygwin/dll_init.h | 4 | ||||
-rw-r--r-- | winsup/cygwin/fork.cc | 15 |
3 files changed, 36 insertions, 9 deletions
diff --git a/winsup/cygwin/dll_init.cc b/winsup/cygwin/dll_init.cc index f94c6698d..2204533c6 100644 --- a/winsup/cygwin/dll_init.cc +++ b/winsup/cygwin/dll_init.cc @@ -306,8 +306,9 @@ dll_list::alloc (HINSTANCE h, per_process *p, dll_type type) guard (true); /* Already loaded? For linked DLLs, only compare the basenames. Linked DLLs are loaded using just the basename and the default DLL search path. - The Windows loader picks up the first one it finds. */ - dll *d = (type == DLL_LINK) ? dlls.find_by_modname (modname) : dlls[ntname]; + The Windows loader picks up the first one it finds. + This also applies to cygwin1.dll and the main-executable (DLL_SELF). */ + dll *d = (type != DLL_LOAD) ? dlls.find_by_modname (modname) : dlls[ntname]; if (d) { /* We only get here in the forkee. */ @@ -339,7 +340,8 @@ dll_list::alloc (HINSTANCE h, per_process *p, dll_type type) d->modname = d->ntname + (modname - ntname); d->handle = h; d->count = 0; /* Reference counting performed in dlopen/dlclose. */ - d->has_dtors = true; + /* DLL_SELF dtors (main-executable, cygwin1.dll) are run elsewhere */ + d->has_dtors = type != DLL_SELF; d->p = p; d->ndeps = 0; d->deps = NULL; @@ -526,7 +528,7 @@ dll_list::find (void *retaddr) dll *d = &start; while ((d = d->next)) - if (d->handle == h) + if (d->type != DLL_SELF && d->handle == h) break; return d; } @@ -566,11 +568,22 @@ dll_list::detach (void *retaddr) void dll_list::init () { + track_self (); + /* Walk the dll chain, initializing each dll */ dll *d = &start; dll_global_dtors_recorded = d->next != NULL; while ((d = d->next)) - d->init (); + if (d->type != DLL_SELF) /* linked and early loaded dlls */ + d->init (); +} + +void +dll_list::track_self () +{ + /* for cygwin1.dll and main-executable: maintain hardlinks only */ + alloc (cygwin_hmodule, user_data, DLL_SELF); + main_executable = alloc (GetModuleHandle (NULL), user_data, DLL_SELF); } #define A64K (64 * 1024) @@ -637,7 +650,7 @@ dll_list::reserve_space () /* Reload DLLs after a fork. Iterates over the list of dynamically loaded DLLs and attempts to load them in the same place as they were loaded in the - parent. */ + parent. Updates main-executable and cygwin1.dll tracking. */ void dll_list::load_after_fork (HANDLE parent) { @@ -647,6 +660,7 @@ dll_list::load_after_fork (HANDLE parent) in_load_after_fork = true; if (reload_on_fork) load_after_fork_impl (parent, dlls.istart (DLL_LOAD), 0); + track_self (); in_load_after_fork = false; } diff --git a/winsup/cygwin/dll_init.h b/winsup/cygwin/dll_init.h index 4897c420f..369fc5427 100644 --- a/winsup/cygwin/dll_init.h +++ b/winsup/cygwin/dll_init.h @@ -40,6 +40,7 @@ struct per_module typedef enum { DLL_NONE, + DLL_SELF, /* main-program.exe, cygwin1.dll */ DLL_LINK, DLL_LOAD, DLL_ANY @@ -75,6 +76,8 @@ struct dll class dll_list { + void track_self (); + dll *end; dll *hold; dll_type hold_type; @@ -94,6 +97,7 @@ public: return nt_max_path_buffer; } + dll *main_executable; dll start; int loaded_dlls; int reload_on_fork; diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc index c78e5cf3b..adcd1d7ad 100644 --- a/winsup/cygwin/fork.cc +++ b/winsup/cygwin/fork.cc @@ -175,7 +175,7 @@ frok::child (volatile char * volatile here) if (fixup_shms_after_fork ()) api_fatal ("recreate_shm areas after fork failed"); - /* load dynamic dlls, if any */ + /* load dynamic dlls, if any, re-track main-executable and cygwin1.dll */ dlls.load_after_fork (hParent); cygheap->fdtab.fixup_after_fork (hParent); @@ -310,11 +310,20 @@ frok::parent (volatile char * volatile stack_here) while (1) { + PCWCHAR forking_progname = NULL; + if (dlls.main_executable) + forking_progname = dll_list::buffered_shortname + (dlls.main_executable->ntname); + if (!forking_progname || !*forking_progname) + forking_progname = myself->progname; + syscall_printf ("CreateProcessW (%W, %W, 0, 0, 1, %y, 0, 0, %p, %p)", - myself->progname, myself->progname, c_flags, &si, &pi); + forking_progname, myself->progname, c_flags, &si, &pi); hchild = NULL; - rc = CreateProcessW (myself->progname, /* image to run */ + /* cygwin1.dll may reuse the forking_progname buffer, even + in case of failure: don't reuse forking_progname later */ + rc = CreateProcessW (forking_progname, /* image to run */ GetCommandLineW (), /* Take same space for command line as in parent to make sure child stack is allocated |