#4661 closed defect (fixed)

GCC 12 generates wrong code

Reported by: Chris Johns Owned by: Chris Johns <chrisj@…>
Priority: high Milestone: 6.1
Component: tool/gcc Version: 6
Severity: blocker Keywords:
Cc: Blocked By:
Blocking:

Description

Calling exit() in a C++ application results in std::terminate() being called.

The std::ios_base::Init::~Init() destructor flushes std::cout, std::cerr and std::clog. The flush of std::cerr results in terminate being called.

The ios_base class uses a sentry to check the state. The code in it's destructor is:

if (bool(_M_os.flags() & ios_base::unitbuf) && !uncaught_exception())  

The std::cerr object has ios_base::unitbuf set so uncaught_exception() is called. This call gets the cxa globals:

__cxa_eh_globals *globals = __cxa_get_globals (); 

The __cxa_get_globals() checks if the ec_globals init object:

static __eh_globals_init init;

to see if it is still valid and the state is:

(gdb) p /x init
$2 = {
  _M_key = 0x13010001,
  _M_init = 0x1
}

However the static destructor has run and the POSIX key has been deleted. This results in std::terminate() being called.

The code for the destructor on ARM is:

006562e0 <__eh_globals_init::~__eh_globals_init()>:
  6562e0:       7903            ldrb    r3, [r0, #4]
  6562e2:       b510            push    {r4, lr}
  6562e4:       4604            mov     r4, r0
  6562e6:       b90b            cbnz    r3, 6562ec <__eh_globals_init::~__eh_globals_init()+0xc>
  6562e8:       4620            mov     r0, r4
  6562ea:       bd10            pop     {r4, pc}
  6562ec:       6800            ldr     r0, [r0, #0]
  6562ee:       f04d fe6b       bl      6a3fc8 <pthread_key_delete>
  6562f2:       4620            mov     r0, r4
  6562f4:       bd10            pop     {r4, pc}

and for aarch64 it is:

0000000010222c30 <__eh_globals_init::~__eh_globals_init()>:
    10222c30:   39401001        ldrb    w1, [x0, #4]
    10222c34:   35000041        cbnz    w1, 10222c3c <__eh_globals_init::~__eh_globals_init()+0xc>
    10222c38:   d65f03c0        ret
    10222c3c:   a9bf7bfd        stp     x29, x30, [sp, #-16]!
    10222c40:   910003fd        mov     x29, sp
  return pthread_key_delete (__key);
    10222c44:   b9400000        ldr     w0, [x0]
    10222c48:   94008806        bl      10244c60 <pthread_key_delete>
    10222c4c:   a8c17bfd        ldp     x29, x30, [sp], #16
    10222c50:   d65f03c0        ret

The _M_init boolean is not set to false.

Change History (3)

comment:2 Changed on 06/09/22 at 02:21:00 by Chris Johns <chrisj@…>

In 80aea6a/rtems:

testsuite/libtests: Add exit03 to test exit() with C++

Updates #4661

comment:3 Changed on 07/19/22 at 06:02:18 by Chris Johns <chrisj@…>

Owner: set to Chris Johns <chrisj@…>
Resolution: fixed
Status: newclosed

In a2bda89/rtems-source-builder:

gcc12/libstdc++: Fix lifetime bugs for non-TLS eh_globals

  • This is the fix from PR105880:

https://gcc.gnu.org/bugzilla/attachment.cgi?id=53103

Closes #4661

Note: See TracTickets for help on using tickets.