abort during exit() with a dynamically loaded C++ library
Jon TURNEY
jon.turney@dronecode.org.uk
Mon Jul 7 13:58:00 GMT 2014
On 17/06/2014 19:11, Jon TURNEY wrote:
> I think I have found a problem when building programs using the latest
> mesa library, where abort is being called during exit()
>
> This seems to be x86 specific, and looks like it is somehow related to
> having a C++ library dynamically loaded by a C program.
>
> I think I have reduced it to the following test case:
So, this seems to be related to this patch [1], to fix a different abort
during __gcc_deregister_frame()
[1] https://sourceware.org/ml/cygwin/2013-07/msg00528.html
Since this code is baked into libgcc itself, that patch has the
side-effect of making libgcc pin itself in memory.
I can't really tell from what's written there if that was deliberate or
not, but it seems that it introduces a different problem when the
executable doesn't have a dependency on libgcc.
> test.c:
>
> #include <assert.h>
> #include <dlfcn.h>
>
> int main()
> {
> void *h = dlopen("dllib.dll", 0);
> assert(h);
> dlclose(h);
The problem can be worked around by adding code to force libgcc to get
unloaded here, which seems to support this theory, e.g.
+#define LIBGCC_SONAME "cyggcc_s-1.dll"
+ HANDLE hmod_libgcc = GetModuleHandle(LIBGCC_SONAME);
+ FreeLibrary(hmod_libgcc);
> }
Attached is a patch which modifies __gcc_register_frame() to avoid it
pinning itself in memory.
Alternatively, as one of the emails in the linked thread says [2], the
assert in __deregister_frame_info_bases() itself could be removed.
[2] http://www.mail-archive.com/gcc@gcc.gnu.org/msg68286.html
-------------- next part --------------
--- cygming-crtbegin.c.bak 2014-07-03 16:41:43.116600000 +0100
+++ cygming-crtbegin.c 2014-07-03 18:39:07.436800000 +0100
@@ -99,8 +99,21 @@
if (h)
{
- /* Increasing the load-count of LIBGCC_SONAME DLL. */
- hmod_libgcc = LoadLibrary (LIBGCC_SONAME);
+ /*
+ Increase the load-count of the LIBGCC_SONAME DLL by one, so that it remains
+ loaded as long as this module is, so that __gcc_deregister_frame() will call
+ __deregister_frame_info() in that DLL, to match the register_frame_info()
+ we do now.
+
+ Unless this *is* LIBGCC_SONAME DLL, where increasing our own load-count would
+ make us self-pinning.
+ */
+ HMODULE hmod_this = 0;
+ GetModuleHandleEx (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+ (LPCTSTR)__gcc_register_frame, &hmod_this);
+ if (hmod_this != h)
+ hmod_libgcc = LoadLibrary (LIBGCC_SONAME);
+
register_frame_fn = (void (*) (const void *, struct object *))
GetProcAddress (h, "__register_frame_info");
}
-------------- next part --------------
--
Problem reports: http://cygwin.com/problems.html
FAQ: http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
More information about the Cygwin
mailing list