Bug 61752 - on cygwin, aborts during exit() with a dynamically loaded C++ library
Summary: on cygwin, aborts during exit() with a dynamically loaded C++ library
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libgcc (show other bugs)
Version: 4.8.3
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-07-08 16:58 UTC by Jon Turney
Modified: 2020-01-12 21:42 UTC (History)
0 users

See Also:
Host:
Target: i686-pc-cygwin
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
Patch to cygming-crtbegin.c to prevent libgcc pinning itself in memory (561 bytes, patch)
2014-07-08 17:03 UTC, Jon Turney
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Jon Turney 2014-07-08 16:58:14 UTC
There seems to be a problem somehow related to having a C++ library which does depend on libgcc dynamically loaded by a C program which doesn't depend on libgcc, where abort is being called during exit()

This seems to be specific to x86 cygwin/mingw targets with dw2 eh

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
Comment 1 Jon Turney 2014-07-08 17:03:47 UTC
Created attachment 33092 [details]
Patch to cygming-crtbegin.c to prevent libgcc pinning itself in memory

This seems to be caused by the fix for pr 57982, to fix a different abort during __gcc_deregister_frame()

Since that change 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.

Attached is a patch which modifies __gcc_register_frame() to avoid it pinning itself in memory.

Alternatively, as [1] says, the assert in __deregister_frame_info_bases() itself could be removed. 

[1] http://www.mail-archive.com/gcc@gcc.gnu.org/msg68286.html
Comment 2 Jon Turney 2014-07-22 13:13:51 UTC
Better patch: https://cygwin.com/ml/cygwin/2014-07/msg00180.html
Comment 3 Jon Turney 2020-01-12 21:42:26 UTC
(In reply to Jon Turney from comment #2)
> Better patch: https://cygwin.com/ml/cygwin/2014-07/msg00180.html

That patch was applied as svn commit 213009.