unhandled C++ exceptions not propagating

Ken Brown kbrown@cornell.edu
Sun Aug 16 22:38:24 GMT 2020


On 8/16/2020 10:56 AM, Ken Brown via Cygwin wrote:
> On 8/16/2020 9:52 AM, Takashi Yano via Cygwin wrote:
>> On Sun, 16 Aug 2020 09:21:24 -0400
>> Ken Brown via Cygwin <cygwin@cygwin.com> wrote:
>>> On 8/15/2020 11:53 PM, Takashi Yano via Cygwin wrote:
>>>> On Sat, 15 Aug 2020 20:38:01 -0300
>>>> David McFarland via Cygwin <cygwin@cygwin.com> wrote:
>>>>>
>>>>> I was just debugging a c++ app (b2 build system from boost), and noticed
>>>>> that it would appear to exit unexpectedly without an error.  This turned
>>>>> out to be when an unhandled C++ exception was thrown.
>>>>>
>>>>> On a fresh install of cygwin with gcc-g++, this program will throw an
>>>>> exception from the std::string constructor:
>>>>>
>>>>> c++ -x c++ - <<END
>>>>> #include <string>
>>>>> int main() { std::string str(nullptr); return 0; }
>>>>> END
>>>>>
>>>>> When it's executed from the shell it returns zero, but execution stops
>>>>> at the exception.
>>>>>
>>>>> $ ./a; echo $?
>>>>> 0
>>>>>
>>>>> When executed under gdb, the exception is caught, and the process exits
>>>>> non-zero when continued:
>>>>>
>>>>> (gdb) r
>>>>> Starting program: /home/corngood/a
>>>>> [New Thread 4300.0x1390]
>>>>> [New Thread 4300.0x1d24]
>>>>> [New Thread 4300.0x1d48]
>>>>> [New Thread 4300.0x80c]
>>>>> gdb: unknown target exception 0x20474343 at 0x7ff8d2cfa799
>>>>> Thread 1 "a" received signal ?, Unknown signal.
>>>>> 0x00007ff8d2cfa799 in RaiseException () from 
>>>>> /cygdrive/c/WINDOWS/System32/KERNELBASE.dll
>>>>> (gdb) c
>>>>> Continuing.
>>>>> [Thread 4300.0x1d24 exited with code 541541187]
>>>>> [Thread 4300.0x1870 exited with code 541541187]
>>>>> [Thread 4300.0x1d48 exited with code 541541187]
>>>>> [Thread 4300.0x1390 exited with code 541541187]
>>>>> [Inferior 1 (process 4300) exited with code 04021641503]
>>>>> (gdb)
>>>>>
>>>>> When executed under strace, it exits with an error as expected:
>>>>>
>>>>> $ strace -o /dev/null a; echo $?
>>>>> 67
>>>>>
>>>>> That's as far as I've investigated so far.
>>>>
>>>> Is this the same issue with
>>>> https://cygwin.com/pipermail/cygwin/2019-October/242795.html ?
>>>>
>>>> As far as I tested, this does not occur in 32-bit cygwin.
>>>
>>> This doesn't seem to be a new issue.  I found the following report from 6 years
>>> ago, on Cygwin 1.7.30 with GCC 4.9.0:
>>>
>>> https://stackoverflow.com/questions/24402412/program-executed-on-cygwin-does-not-report-a-thrown-exception 
>>>
>>
>> Thanks for the information. But I still wonder why 32-bit and 64-bit
>> cygwin behave differently.
> 
> I'm no C++ expert, but my understanding after a brief internet search is that an 
> uncaught exception is supposed to cause std::terminate to be called.  So I 
> installed gcc-debuginfo and ran the OP's test case under gdb with a breakpoint 
> at 'terminate'.  On 32-bit Cygwin I got the expected behavior:
> 
> Thread 1 "exception_test" hit Breakpoint 1, std::terminate ()
>      at /usr/src/debug/gcc-9.3.0-2/libstdc++-v3/libsupc++/eh_terminate.cc:96
> 96        __atomic_load (&__terminate_handler, &func, __ATOMIC_ACQUIRE);
> (gdb) bt
> #0  std::terminate ()
>      at /usr/src/debug/gcc-9.3.0-2/libstdc++-v3/libsupc++/eh_terminate.cc:96
> #1  0x57c45909 in __cxxabiv1::__cxa_throw (obj=obj@entry=0x800396e8,
>      tinfo=tinfo@entry=0x57c646a8 <typeinfo for std::logic_error>,
>      dest=0x57be6c60 <std::logic_error::~logic_error()>)
>      at /usr/src/debug/gcc-9.3.0-2/libstdc++-v3/libsupc++/eh_throw.cc:95
> #2  0x57c49223 in std::__throw_logic_error (
>      __s=__s@entry=0x57c60160 <cplus_demangle_builtin_types+10272> "basic_string::
> _S_construct null not valid")
>      at /usr/src/debug/gcc-9.3.0-2/libstdc++-v3/src/c++11/functexcept.cc:66
> [...]
> 
> On 64-bit Cygwin, however, I got the behavior reported by the OP:
> 
> gdb: unknown target exception 0x20474343 at 0x7ff8cccca719
> 
> Thread 1 "exception_test" received signal ?, Unknown signal.
> 0x00007ff8cccca719 in RaiseException () from /c/WINDOWS/System32/KERNELBASE.dll
> (gdb) c
> Continuing.
> [Thread 4508.0x3e20 exited with code 541541187]
> [Thread 4508.0x5bc exited with code 541541187]
> [Thread 4508.0x5ee8 exited with code 541541187]
> [Thread 4508.0x1cd0 exited with code 541541187]
> [Inferior 1 (process 4508) exited with code 04021641503]
> 
> Note that the breakpoint at 'terminate' is not reached.  I tried putting a 
> breakpoint at __cxa_throw and stepping through from there, but I don't really 
> understand what's going on.  Someone who knows the innards of exception handling 
> will have to look at this.

One further comment, and then I'll shut up and leave it to people who know what 
they're talking about: In the 64-bit case, the function _Unwind_RaiseException 
in libgcc/unwind-seh.c gets called, and it calls the Win32 function 
RaiseException as follows:

   RaiseException (STATUS_GCC_THROW, 0, 1, (ULONG_PTR *)&exc);

Then the following comment appears:

   /* The exception handler installed in crt0 will continue any GCC
      exception that reaches there (and isn't marked non-continuable).
      Returning allows the C++ runtime to call std::terminate.  */

Apparently this doesn't actually happen.

Ken


More information about the Cygwin mailing list