* 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>
|
2009-08-12 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* fhandler_socket.cc (fhandler_socket::accept): Always use local
|
* 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
|
/* 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 =
|
struct per_process_cxx_malloc default_cygwin_cxx_malloc =
|
||||||
{
|
{
|
||||||
|
@ -93,7 +93,28 @@ dlopen (const char *name, int)
|
|||||||
wchar_t *path = tp.w_get ();
|
wchar_t *path = tp.w_get ();
|
||||||
|
|
||||||
pc.get_wide_win32_path (path);
|
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);
|
ret = (void *) LoadLibraryW (path);
|
||||||
|
|
||||||
|
/* Restore original cxx_malloc pointer. */
|
||||||
|
__cygwin_user_data.cxx_malloc = tmp_malloc;
|
||||||
|
|
||||||
if (ret == NULL)
|
if (ret == NULL)
|
||||||
__seterrno ();
|
__seterrno ();
|
||||||
}
|
}
|
||||||
|
@ -328,6 +328,26 @@ dll_dllcrt0_1 (VOID *x)
|
|||||||
|
|
||||||
bool linked = !in_forkee && !cygwin_finished_initializing;
|
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. */
|
/* Partially initialize Cygwin guts for non-cygwin apps. */
|
||||||
if (dynamically_loaded && user_data->magic_biscuit == 0)
|
if (dynamically_loaded && user_data->magic_biscuit == 0)
|
||||||
dll_crt0 (p);
|
dll_crt0 (p);
|
||||||
|
@ -33,6 +33,7 @@ CDECL_END \
|
|||||||
static HINSTANCE storedHandle; \
|
static HINSTANCE storedHandle; \
|
||||||
static DWORD storedReason; \
|
static DWORD storedReason; \
|
||||||
static void* storedPtr; \
|
static void* storedPtr; \
|
||||||
|
int __dynamically_loaded; \
|
||||||
\
|
\
|
||||||
static int __dllMain (int a, char **b, char **c) \
|
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; \
|
storedHandle = h; \
|
||||||
storedReason = reason; \
|
storedReason = reason; \
|
||||||
storedPtr = ptr; \
|
storedPtr = ptr; \
|
||||||
|
__dynamically_loaded = (ptr == NULL); \
|
||||||
dll_index = cygwin_attach_dll (h, &__dllMain); \
|
dll_index = cygwin_attach_dll (h, &__dllMain); \
|
||||||
if (dll_index == (DWORD) -1) \
|
if (dll_index == (DWORD) -1) \
|
||||||
ret = 0; \
|
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. */
|
/* Avoid an info message from linker when linking applications. */
|
||||||
extern __declspec(dllimport) struct _reent *_impure_ptr;
|
extern __declspec(dllimport) struct _reent *_impure_ptr;
|
||||||
|
|
||||||
|
/* Initialised in _cygwin_dll_entry. */
|
||||||
|
extern int __dynamically_loaded;
|
||||||
|
|
||||||
#undef environ
|
#undef environ
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
@ -70,11 +73,13 @@ _cygwin_crt0_common (MainFunc f, per_process *u)
|
|||||||
per_process *newu = (per_process *) cygwin_internal (CW_USER_DATA);
|
per_process *newu = (per_process *) cygwin_internal (CW_USER_DATA);
|
||||||
int uwasnull;
|
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)
|
if (u != NULL)
|
||||||
uwasnull = 0; /* Caller allocated space for per_process structure. */
|
uwasnull = 0; /* Caller allocated space for per_process structure. */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u = newu; /* Using DLL built-in per_process. */
|
u = newu; /* Using DLL built-in per_process. */
|
||||||
uwasnull = 1; /* Remember for later. */
|
uwasnull = 1; /* Remember for later. */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,8 +119,10 @@ _cygwin_crt0_common (MainFunc f, per_process *u)
|
|||||||
u->realloc = &realloc;
|
u->realloc = &realloc;
|
||||||
u->calloc = &calloc;
|
u->calloc = &calloc;
|
||||||
|
|
||||||
/* Likewise for the C++ memory operators - if any. */
|
/* Likewise for the C++ memory operators, if any, but not if we
|
||||||
if (newu && newu->cxx_malloc)
|
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. */
|
/* Inherit what we don't override. */
|
||||||
#define CONDITIONALLY_OVERRIDE(MEMBER) \
|
#define CONDITIONALLY_OVERRIDE(MEMBER) \
|
||||||
@ -129,12 +136,10 @@ _cygwin_crt0_common (MainFunc f, per_process *u)
|
|||||||
CONDITIONALLY_OVERRIDE(oper_new___nt);
|
CONDITIONALLY_OVERRIDE(oper_new___nt);
|
||||||
CONDITIONALLY_OVERRIDE(oper_delete_nt);
|
CONDITIONALLY_OVERRIDE(oper_delete_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. */
|
/* Setup the module handle so fork can get the path name. */
|
||||||
u->hmodule = GetModuleHandle (0);
|
u->hmodule = GetModuleHandle (0);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user