* dcrt0.cc (cygwin_atexit): Add workaround for broken atexit calls
in __gcc_register_frame of DLLs built with gcc-4.8.3-3.
This commit is contained in:
parent
8134be8ac2
commit
b7749822ed
|
@ -1,3 +1,8 @@
|
||||||
|
2014-10-27 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* dcrt0.cc (cygwin_atexit): Add workaround for broken atexit calls
|
||||||
|
in __gcc_register_frame of DLLs built with gcc-4.8.3-3.
|
||||||
|
|
||||||
2014-10-27 Corinna Vinschen <corinna@vinschen.de>
|
2014-10-27 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* dlfcn.cc (dlopen): Drop patch accommodating SetDllDiretory from
|
* dlfcn.cc (dlopen): Drop patch accommodating SetDllDiretory from
|
||||||
|
|
|
@ -1236,7 +1236,37 @@ extern "C" int
|
||||||
cygwin_atexit (void (*fn) (void))
|
cygwin_atexit (void (*fn) (void))
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
dll *d = dlls.find ((void *) _my_tls.retaddr ());
|
dll *d = dlls.find ((void *) _my_tls.retaddr ());
|
||||||
|
#ifdef __x86_64__
|
||||||
|
/* x86_64 DLLs created with GCC 4.8.3-3 register __gcc_deregister_frame
|
||||||
|
as atexit function using a call to atexit, rather than __cxa_atexit.
|
||||||
|
Due to GCC's aggressive optimizing, cygwin_atexit doesn't get the correct
|
||||||
|
return address on the stack. As a result it fails to get the HMODULE of
|
||||||
|
the caller and thus calls atexit rather than __cxa_atexit. Then, if the
|
||||||
|
module gets dlclosed, __cxa_finalize (called from dll_list::detach) can't
|
||||||
|
remove __gcc_deregister_frame from the atexit function chain. So at
|
||||||
|
process exit, __call_exitprocs calls __gcc_deregister_frame while the
|
||||||
|
module is already unloaded and the __gcc_deregister_frame function not
|
||||||
|
available ==> SEGV.
|
||||||
|
|
||||||
|
Workaround: If dlls.find fails, and _my_tls.retaddr is a Cygwin function
|
||||||
|
address, and fn is a function address in another DLL, try to find the
|
||||||
|
dll entry of the DLL containing fn. Then check if fn is the address of
|
||||||
|
the DLLs __gcc_deregister_frame function. If so, proceed by calling
|
||||||
|
__cxa_atexit, otherwise call atexit. */
|
||||||
|
extern void *__image_base__;
|
||||||
|
if (!d
|
||||||
|
&& (uintptr_t) _my_tls.retaddr () >= (uintptr_t) &__image_base__
|
||||||
|
&& (uintptr_t) _my_tls.retaddr () <= (uintptr_t) &_cygheap_start
|
||||||
|
&& (uintptr_t) fn > (uintptr_t) &_cygheap_start)
|
||||||
|
{
|
||||||
|
d = dlls.find ((void *) fn);
|
||||||
|
if (d && (void *) GetProcAddress (d->handle, "__gcc_deregister_frame")
|
||||||
|
!= fn)
|
||||||
|
d = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
res = d ? __cxa_atexit ((void (*) (void *)) fn, NULL, d->handle) : atexit (fn);
|
res = d ? __cxa_atexit ((void (*) (void *)) fn, NULL, d->handle) : atexit (fn);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,3 +83,6 @@ Bug Fixes
|
||||||
- Fix a SEGV in cygcheck if the environment variable COMSPEC is not, or
|
- Fix a SEGV in cygcheck if the environment variable COMSPEC is not, or
|
||||||
incorrectly set.
|
incorrectly set.
|
||||||
Addresses: https://cygwin.com/ml/cygwin/2014-10/msg00292.html
|
Addresses: https://cygwin.com/ml/cygwin/2014-10/msg00292.html
|
||||||
|
|
||||||
|
- Fix a SEGV in some 64 bit applications explicitely dlclosing DLLs.
|
||||||
|
Addresses: https://cygwin.com/ml/cygwin/2014-10/msg00402.html
|
||||||
|
|
Loading…
Reference in New Issue