* cxx.cc (default_cygwin_cxx_malloc): Enhance commenting.
* dll_init.cc (dll_dllcrt0_1): Likewise. * dlfcn.cc (dlopen): Prevent dlopen()'d DLL from installing any cxx malloc overrides. * include/cygwin/cygwin_dll.h (__dynamically_loaded): New variable. * lib/_cygwin_crt0_common.cc (_cygwin_crt0_common): Check it and only install cxx malloc overrides when statically loaded. Extend comments.
This commit is contained in:
parent
61189f19de
commit
ce5eb135a2
|
@ -1,3 +1,14 @@
|
|||
2009-08-13 Corinna Vinschen <corinna@vinschen.de>
|
||||
Dave Korn <dave.korn.cygwin@googlemail.com>
|
||||
|
||||
* cxx.cc (default_cygwin_cxx_malloc): Enhance commenting.
|
||||
* dll_init.cc (dll_dllcrt0_1): Likewise.
|
||||
* dlfcn.cc (dlopen): Prevent dlopen()'d DLL from installing any
|
||||
cxx malloc overrides.
|
||||
* include/cygwin/cygwin_dll.h (__dynamically_loaded): New variable.
|
||||
* lib/_cygwin_crt0_common.cc (_cygwin_crt0_common): Check it and only
|
||||
install cxx malloc overrides when statically loaded. Extend comments.
|
||||
|
||||
2009-08-12 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* fhandler_socket.cc (fhandler_socket::accept): Always use local
|
||||
|
|
|
@ -87,7 +87,10 @@ __cxa_guard_release ()
|
|||
}
|
||||
|
||||
/* These routines are made available as last-resort fallbacks
|
||||
for the application. Should not be used in practice. */
|
||||
for the application. Should not be used in practice; the
|
||||
entries in this struct get overwritten by each DLL as it
|
||||
is loaded, and libstdc++ will override the whole lot first
|
||||
thing of all. */
|
||||
|
||||
struct per_process_cxx_malloc default_cygwin_cxx_malloc =
|
||||
{
|
||||
|
|
|
@ -93,7 +93,28 @@ dlopen (const char *name, int)
|
|||
wchar_t *path = tp.w_get ();
|
||||
|
||||
pc.get_wide_win32_path (path);
|
||||
|
||||
/* Workaround for broken DLLs built against Cygwin versions 1.7.0-49
|
||||
up to 1.7.0-57. They override the cxx_malloc pointer in their
|
||||
DLL initialization code even if loaded dynamically. This is a
|
||||
no-no since a later dlclose lets cxx_malloc point into nirvana.
|
||||
The below kludge "fixes" that by reverting the original cxx_malloc
|
||||
pointer after LoadLibrary. This implies that their overrides
|
||||
won't be applied; that's OK. All overrides should be present at
|
||||
final link time, as Windows doesn't allow undefined references;
|
||||
it would actually be wrong for a dlopen'd DLL to opportunistically
|
||||
override functions in a way that wasn't known then. We're not
|
||||
going to try and reproduce the full ELF dynamic loader here! */
|
||||
|
||||
/* Store original cxx_malloc pointer. */
|
||||
struct per_process_cxx_malloc *tmp_malloc;
|
||||
tmp_malloc = __cygwin_user_data.cxx_malloc;
|
||||
|
||||
ret = (void *) LoadLibraryW (path);
|
||||
|
||||
/* Restore original cxx_malloc pointer. */
|
||||
__cygwin_user_data.cxx_malloc = tmp_malloc;
|
||||
|
||||
if (ret == NULL)
|
||||
__seterrno ();
|
||||
}
|
||||
|
|
|
@ -328,6 +328,26 @@ dll_dllcrt0_1 (VOID *x)
|
|||
|
||||
bool linked = !in_forkee && !cygwin_finished_initializing;
|
||||
|
||||
/* 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,
|
||||
when loaded either statically or dynamically. Because this leaves
|
||||
a stale pointer into demapped memory space if the DLL is unloaded
|
||||
by a call to dlclose, we prevent this happening for dynamically
|
||||
loaded DLLS in dlopen by saving and restoring cxx_malloc around
|
||||
the call to LoadLibrary, which invokes the DLL's startup sequence.
|
||||
Modern DLLs won't even attempt to override the pointer when loaded
|
||||
statically, but will write their overrides directly into the
|
||||
struct it points to. With all modern DLLs, this will remain the
|
||||
default_cygwin_cxx_malloc struct in cxx.cc, but if any broken DLLs
|
||||
are in the mix they will have overridden the pointer and subsequent
|
||||
overrides will go into their embedded cxx_malloc structs. This is
|
||||
almost certainly not a problem as they can never be unloaded, but
|
||||
if we ever did want to do anything about it, we could check here to
|
||||
see if the pointer had been altered in the early parts of the DLL's
|
||||
startup, and if so copy back the new overrides and reset it here.
|
||||
However, that's just a note for the record; at the moment, we can't
|
||||
see any need to worry about this happening. */
|
||||
|
||||
/* Partially initialize Cygwin guts for non-cygwin apps. */
|
||||
if (dynamically_loaded && user_data->magic_biscuit == 0)
|
||||
dll_crt0 (p);
|
||||
|
|
|
@ -33,6 +33,7 @@ CDECL_END \
|
|||
static HINSTANCE storedHandle; \
|
||||
static DWORD storedReason; \
|
||||
static void* storedPtr; \
|
||||
int __dynamically_loaded; \
|
||||
\
|
||||
static int __dllMain (int a, char **b, char **c) \
|
||||
{ \
|
||||
|
@ -53,6 +54,7 @@ int WINAPI _cygwin_dll_entry (HINSTANCE h, DWORD reason, void *ptr) \
|
|||
storedHandle = h; \
|
||||
storedReason = reason; \
|
||||
storedPtr = ptr; \
|
||||
__dynamically_loaded = (ptr == NULL); \
|
||||
dll_index = cygwin_attach_dll (h, &__dllMain); \
|
||||
if (dll_index == (DWORD) -1) \
|
||||
ret = 0; \
|
||||
|
|
|
@ -40,6 +40,9 @@ extern WEAK void operator delete[](void *p, const std::nothrow_t &nt) throw()
|
|||
/* Avoid an info message from linker when linking applications. */
|
||||
extern __declspec(dllimport) struct _reent *_impure_ptr;
|
||||
|
||||
/* Initialised in _cygwin_dll_entry. */
|
||||
extern int __dynamically_loaded;
|
||||
|
||||
#undef environ
|
||||
|
||||
extern "C"
|
||||
|
@ -70,11 +73,13 @@ _cygwin_crt0_common (MainFunc f, per_process *u)
|
|||
per_process *newu = (per_process *) cygwin_internal (CW_USER_DATA);
|
||||
int uwasnull;
|
||||
|
||||
/* u is non-NULL if we are in a DLL, and NULL in the main exe.
|
||||
newu is the Cygwin DLL's internal per_process and never NULL. */
|
||||
if (u != NULL)
|
||||
uwasnull = 0; /* Caller allocated space for per_process structure. */
|
||||
else
|
||||
{
|
||||
u = newu; /* Using DLL built-in per_process. */
|
||||
u = newu; /* Using DLL built-in per_process. */
|
||||
uwasnull = 1; /* Remember for later. */
|
||||
}
|
||||
|
||||
|
@ -114,8 +119,10 @@ _cygwin_crt0_common (MainFunc f, per_process *u)
|
|||
u->realloc = &realloc;
|
||||
u->calloc = &calloc;
|
||||
|
||||
/* Likewise for the C++ memory operators - if any. */
|
||||
if (newu && newu->cxx_malloc)
|
||||
/* Likewise for the C++ memory operators, if any, but not if we
|
||||
were dlopen()'d, as we might get dlclose()'d and that would
|
||||
leave stale function pointers behind. */
|
||||
if (newu && newu->cxx_malloc && !__dynamically_loaded)
|
||||
{
|
||||
/* Inherit what we don't override. */
|
||||
#define CONDITIONALLY_OVERRIDE(MEMBER) \
|
||||
|
@ -129,12 +136,10 @@ _cygwin_crt0_common (MainFunc f, per_process *u)
|
|||
CONDITIONALLY_OVERRIDE(oper_new___nt);
|
||||
CONDITIONALLY_OVERRIDE(oper_delete_nt);
|
||||
CONDITIONALLY_OVERRIDE(oper_delete___nt);
|
||||
/* Now update the resulting set into the global redirectors. */
|
||||
*newu->cxx_malloc = __cygwin_cxx_malloc;
|
||||
}
|
||||
|
||||
/* Now update the resulting set into the global redirectors. */
|
||||
if (newu)
|
||||
newu->cxx_malloc = &__cygwin_cxx_malloc;
|
||||
|
||||
/* Setup the module handle so fork can get the path name. */
|
||||
u->hmodule = GetModuleHandle (0);
|
||||
|
||||
|
|
Loading…
Reference in New Issue