public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
* abort during exit() with a dynamically loaded C++ library
@ 2014-06-17 18:12 Jon TURNEY
  2014-07-07 13:58 ` Jon TURNEY
  0 siblings, 1 reply; 3+ messages in thread
From: Jon TURNEY @ 2014-06-17 18:12 UTC (permalink / raw)
  To: cygwin


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:

test.c:

#include <assert.h>
#include <dlfcn.h>

int main()
{
    void *h = dlopen("dllib.dll", 0);
    assert(h);
    dlclose(h);
}

dllib.c:

#include <fstream>

std::fstream instance;

Makefile:

all:
         g++ -g -O0 -c dllib.cc
         g++ -g -O0 -shared -o dllib.dll dllib.o
         gcc -g -O0 -o test.exe test.c
         ./test


Running under gdb shows gcc_abort() in __deregister_frame_info_bases() 
is being hit

$ gdb test
[...]
Program received signal SIGABRT, Aborted.
0x0028da18 in ?? ()
(gdb) bt
#0  0x0028da18 in ?? ()
#1  0x74f912cc in WriteFile () from 
/cygdrive/c/Windows/syswow64/kernel32.dll
#2  0x610da70c in sig_send(_pinfo*, siginfo_t&, _cygtls*)@12 
(p=p@entry=0x60fd0000, si=..., tls=tls@entry=0x0)
     at /usr/src/debug/cygwin-1.7.30-1/winsup/cygwin/sigproc.cc:638
#3  0x610d7dbc in _pinfo::kill(siginfo_t&)@8 (this=0x60fd0000, si=...)
     at /usr/src/debug/cygwin-1.7.30-1/winsup/cygwin/signal.cc:248
#4  0x610d8286 in kill0 (pid=pid@entry=5044, si=...) at 
/usr/src/debug/cygwin-1.7.30-1/winsup/cygwin/signal.cc:299
#5  0x610d8452 in kill (sig=sig@entry=6, pid=5044) at 
/usr/src/debug/cygwin-1.7.30-1/winsup/cygwin/signal.cc:308
#6  raise (sig=sig@entry=6) at 
/usr/src/debug/cygwin-1.7.30-1/winsup/cygwin/signal.cc:284
#7  0x610d86f3 in abort () at 
/usr/src/debug/cygwin-1.7.30-1/winsup/cygwin/signal.cc:371
#8  0x699134d1 in __deregister_frame_info_bases (begin=0x404038 
<__EH_FRAME_BEGIN__>)
     at /usr/src/debug/gcc-4.8.3-1/libgcc/unwind-dw2-fde.c:216
#9  0x00401182 in __gcc_deregister_frame ()
#10 0x61006466 in do_global_dtors () at 
/usr/src/debug/cygwin-1.7.30-1/winsup/cygwin/dcrt0.cc:62
#11 0x61159aba in __call_exitprocs (code=code@entry=0, d=d@entry=0x0)
     at 
/usr/src/debug/cygwin-1.7.30-1/newlib/libc/stdlib/__call_atexit.c:118
#12 0x611305d8 in exit (code=0) at 
/usr/src/debug/cygwin-1.7.30-1/newlib/libc/stdlib/exit.c:66
#13 0x61006b39 in cygwin_exit (n=0) at 
/usr/src/debug/cygwin-1.7.30-1/winsup/cygwin/dcrt0.cc:1248
#14 0x61008041 in cygwin_exit_return () at 
/usr/src/debug/cygwin-1.7.30-1/winsup/cygwin/dcrt0.cc:1041
#15 0x61005e84 in _cygtls::call2(unsigned long (*)(void*, void*), void*, 
void*)@16 (this=<optimized out>,
     func=func@entry=0x610071d0 <dll_crt0_1(void*)>, arg=arg@entry=0x0, 
buf=buf@entry=0x28cd84)
     at /usr/src/debug/cygwin-1.7.30-1/winsup/cygwin/cygtls.cc:100
#16 0x61005ff6 in _cygtls::call (func=func@entry=0x610071d0 
<dll_crt0_1(void*)>, arg=arg@entry=0x0)
     at /usr/src/debug/cygwin-1.7.30-1/winsup/cygwin/cygtls.cc:30
#17 0x61006f54 in _dll_crt0@0 () at 
/usr/src/debug/cygwin-1.7.30-1/winsup/cygwin/dcrt0.cc:1098
#18 0x00401222 in cygwin_crt0 (f=0x4011a0 <main>) at 
/usr/src/debug/cygwin-1.7.30-1/winsup/cygwin/lib/cygwin_crt0.c:22
#19 0x00401015 in mainCRTStartup () at 
/usr/src/debug/cygwin-1.7.30-1/winsup/cygwin/crt0.c:29

--
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

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: abort during exit() with a dynamically loaded C++ library
  2014-06-17 18:12 abort during exit() with a dynamically loaded C++ library Jon TURNEY
@ 2014-07-07 13:58 ` Jon TURNEY
  2014-07-07 19:33   ` jojelino
  0 siblings, 1 reply; 3+ messages in thread
From: Jon TURNEY @ 2014-07-07 13:58 UTC (permalink / raw)
  To: cygwin

[-- Attachment #1: Type: text/plain, Size: 1548 bytes --]

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


[-- Attachment #2: cygming-crtbegin.c.patch --]
[-- Type: text/plain, Size: 1093 bytes --]

--- 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");
     }

[-- Attachment #3: Type: text/plain, Size: 218 bytes --]

--
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

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: abort during exit() with a dynamically loaded C++ library
  2014-07-07 13:58 ` Jon TURNEY
@ 2014-07-07 19:33   ` jojelino
  0 siblings, 0 replies; 3+ messages in thread
From: jojelino @ 2014-07-07 19:33 UTC (permalink / raw)
  To: cygwin

On 2014-07-07 PM 10:58, Jon TURNEY wrote:
> 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()

The main concern of this crash is the order mismatch between loading and 
unloading dynamic library. It seems that either crtbegin or crtend code 
of i386 libgcc has some pitfall. The mismatch always occurs when main() 
didn't statically link to libgcc.

If my memory serves me correctly, static version of deregister_frame_fn 
is set to wrong address (see cygming-crtbegin.c) by unknown fallacy of 
gnu-ld linker. That is, Object file seems okay, But generated dll breaks 
offset argument resulting in invalid offset operand of memory 
references, although Kai Tietz said in 
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57680 that It had been fixed.

Until the fallacy of gnu-ld is being resolved by someone that has plenty 
of time or someone have workaround against the fallacy of 
ever-not-warranted linker, I'll suggest you to just call 
dlopen("cyggcc_s-1") before dlopen'ing any DLL that has dynamic linkage 
to libgcc. It would be okay for workarounding the problem.
-- 
Regards.


--
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

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2014-07-07 19:33 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-17 18:12 abort during exit() with a dynamically loaded C++ library Jon TURNEY
2014-07-07 13:58 ` Jon TURNEY
2014-07-07 19:33   ` jojelino

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).