* dll_init.cc (dll_list::alloc): Compare linked DLLs by basename only.

Explain why.  Add code to check if a DLL with the same basename but
	different path is the same DLL.  Bail out if not.
	(in_load_after_fork): New static NO_COPY bool to allow to differ
	between linked and loaded DLL at fork.
	(dll_list::load_after_fork): Set in_load_after_fork accordingly.
	(dll_dllcrt0_1): Don't treat DLL as linked if in_load_after_fork is set.
	Drop test for in_forkee.
This commit is contained in:
Corinna Vinschen 2012-03-04 16:47:45 +00:00
parent 50124fc056
commit f5b0d9d414
2 changed files with 41 additions and 4 deletions

View File

@ -1,3 +1,14 @@
2012-03-04 Corinna Vinschen <corinna@vinschen.de>
* dll_init.cc (dll_list::alloc): Compare linked DLLs by basename only.
Explain why. Add code to check if a DLL with the same basename but
different path is the same DLL. Bail out if not.
(in_load_after_fork): New static NO_COPY bool to allow to differ
between linked and loaded DLL at fork.
(dll_list::load_after_fork): Set in_load_after_fork accordingly.
(dll_dllcrt0_1): Don't treat DLL as linked if in_load_after_fork is set.
Drop test for in_forkee.
2012-03-04 Corinna Vinschen <corinna@vinschen.de> 2012-03-04 Corinna Vinschen <corinna@vinschen.de>
* dll_init.cc: Revert pathname changes from 2012-02-08. * dll_init.cc: Revert pathname changes from 2012-02-08.

View File

@ -167,10 +167,13 @@ dll_list::alloc (HINSTANCE h, per_process *p, dll_type type)
if (!wcsncmp (name, L"\\\\?\\", 4)) if (!wcsncmp (name, L"\\\\?\\", 4))
name += 4; name += 4;
DWORD namelen = wcslen (name); DWORD namelen = wcslen (name);
PWCHAR modname = wcsrchr (name, L'\\') + 1;
guard (true); guard (true);
/* Already loaded? */ /* Already loaded? For linked DLLs, only compare the basenames. Linked
dll *d = dlls[name]; 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[name];
if (d) if (d)
{ {
if (!in_forkee) if (!in_forkee)
@ -178,6 +181,21 @@ dll_list::alloc (HINSTANCE h, per_process *p, dll_type type)
else if (d->handle != h) else if (d->handle != h)
fabort ("%W: Loaded to different address: parent(%p) != child(%p)", fabort ("%W: Loaded to different address: parent(%p) != child(%p)",
name, d->handle, h); name, d->handle, h);
/* If this DLL has been linked against, and the full path differs, try
to sanity check if this is the same DLL, just in another path. */
else if (type == DLL_LINK && wcscasecmp (name, d->name)
&& (d->p.data_start != p->data_start
|| d->p.data_start != p->data_start
|| d->p.bss_start != p->bss_start
|| d->p.bss_end != p->bss_end
|| d->p.ctors != p->ctors
|| d->p.dtors != p->dtors))
fabort ("\nLoaded different DLL with same basename in forked child,\n"
"parent loaded: %W\n"
" child loaded: %W\n"
"The DLLs differ, so it's not safe to run the forked child.\n"
"Make sure to remove the offending DLL before trying again.",
d->name, name);
d->p = p; d->p = p;
} }
else else
@ -189,7 +207,7 @@ dll_list::alloc (HINSTANCE h, per_process *p, dll_type type)
supplied info about this DLL. */ supplied info about this DLL. */
d->count = 1; d->count = 1;
wcscpy (d->name, name); wcscpy (d->name, name);
d->modname = wcsrchr (d->name, L'\\') + 1; d->modname = d->name + (modname - name);
d->handle = h; d->handle = h;
d->has_dtors = true; d->has_dtors = true;
d->p = p; d->p = p;
@ -446,6 +464,12 @@ dll_list::reserve_space ()
d->modname, d->handle); d->modname, d->handle);
} }
/* We need the in_load_after_fork flag so dll_dllcrt0_1 can decide at fork
time if this is a linked DLL or a dynamically loaded DLL. In either case,
both, cygwin_finished_initializing and in_forkee are true, so they are not
sufficient to discern the situation. */
static bool NO_COPY in_load_after_fork;
/* Reload DLLs after a fork. Iterates over the list of dynamically loaded /* 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 DLLs and attempts to load them in the same place as they were loaded in the
parent. */ parent. */
@ -455,7 +479,9 @@ dll_list::load_after_fork (HANDLE parent)
// moved to frok::child for performance reasons: // moved to frok::child for performance reasons:
// dll_list::reserve_space(); // dll_list::reserve_space();
in_load_after_fork = true;
load_after_fork_impl (parent, dlls.istart (DLL_LOAD), 0); load_after_fork_impl (parent, dlls.istart (DLL_LOAD), 0);
in_load_after_fork = false;
} }
static int const DLL_RETRY_MAX = 6; static int const DLL_RETRY_MAX = 6;
@ -582,7 +608,7 @@ dll_dllcrt0_1 (VOID *x)
_pei386_runtime_relocator (p); _pei386_runtime_relocator (p);
} }
bool linked = !in_forkee && !cygwin_finished_initializing; bool linked = !cygwin_finished_initializing && !in_load_after_fork;
/* Broken DLLs built against Cygwin versions 1.7.0-49 up to 1.7.0-57 /* Broken DLLs built against Cygwin versions 1.7.0-49 up to 1.7.0-57
override the cxx_malloc pointer in their DLL initialization code, override the cxx_malloc pointer in their DLL initialization code,