libobjc2 icon indicating copy to clipboard operation
libobjc2 copied to clipboard

When mixing C++, ObjC++, and ObjC, something goes wrong in stack unwinding and a crash (abort) ensues

Open lcampbel opened this issue 1 year ago • 3 comments

I boiled this down from a large codebase into the tiniest example I could manage, but it's still six files (including the GNUmakefile) so I'm attaching a tarball. The code executes normally on macOS:

2024-12-07 11:04:20.489861-0500 xtest[83830:4242596] finally
2024-12-07 11:04:20.490356-0500 xtest[83830:4242596] Got expected exception: yup
2024-12-07 11:04:20.490434-0500 xtest[83830:4242596] passed

but on gnustep/linux (Ubuntu 20.04, gnustep-base 1.27.0, libobjc2 2.0.1) it crashes with an abort in libobjc2/eh_personality.c:

2024-12-07 16:03:45.990 xtest[3003478:3003478] finally
2024-12-07 16:03:45.991 xtest[3003478:3003478] Got expected exception: yup
Aborted (core dumped)

with this stack:

#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x00007facc5d1c859 in __GI_abort () at abort.c:79
#2  0x00007facc607b35a in objc_begin_catch () from /home/lcampbel/dev/AkamaiKit-3.7-alsi11-lib64/common/lib/libobjc.so.4.6
#3  0x00000000004023a0 in -[UnitTest xidTest] (self=0x1335488, _cmd=0x408c00 <objc_selector_list+144>) at xtest.m:42
#4  0x000000000040250a in main (argc=<optimized out>, argv=<optimized out>) at xtest.m:75

Weirdly, any of the following tweaks to the code makes the crash go away:

Reversing the order of the tests, changing this:

        [u fooTest];
        [u xidTest];

to this:

        [u xidTest];
        [u fooTest];

Inlining the C++ ctor and dtor, by omitting utest.cc and changing the declarations in utest.h from this:

  xid();
  ~xid();

to this:

  xid() {}
  ~xid() {}

or eliminating the allocation of an xid object in -[Xid init] by removing this line:

    xid u;

There's only one call to abort() in objc_begin_catch:

        // If we have a foreign exception while we have stacked exceptions, we have                                                                                                                                                                                       
        // a problem.  We can't chain them, so we follow the example of C++ and                                                                                                                                                                                           
        // just abort.                                                                                                                                                                                                                                                    
        if (td->caughtExceptions != 0)
        {
                // FIXME: Actually, we can handle a C++ exception if only ObjC                                                                                                                                                                                            
                // exceptions are in-flight                                                                                                                                                                                                                               
                abort();
        }

so I suspect something is not cleaning out td->caughtExceptions properly, but I'm not familiar enough with libobjc2 internals to say any more than that.

lcampbel avatar Dec 07 '24 16:12 lcampbel

Thanks for the report. Unfortunately, things that depend on GNUstep Make are not reproducible because they add a load of flags to the build that are set when you configure GNUstep Make. And, with dependencies on Foundation, things are not possible to integrate with our testing infrastructure. Is it possible for you to provide a minimal reproducible case? Something with no dependencies outside libobjc2 and with all of the command-line flags that you provide?

From the provided files, I can't tell which ABI you're using. The old GCC ABI had a lot of limitations and I'd expect a crash in this case, the GNUstep 2.0 ABI should have fixed them (but may still contain bugs) and I think the GNUstep 1.0 ABI mostly fixed them but had a few corner cases.

davidchisnall avatar Dec 08 '24 11:12 davidchisnall

Thanks. I'm building with clang/llvm, and with these configure options for gnustep-make:

--enable-objc-nonfragile-abi=yes --enable-native-objc-exceptions=yes --with-library-combo=ng-gnu-gnu

which I think means I'm using the new ABI.

I will try to shrink the test case down to a more minimal one but I won't be able to spend time on that for a few days.

  • lc

On Dec 8, 2024, at 06:41, David Chisnall @.***> wrote:

Thanks for the report. Unfortunately, things that depend on GNUstep Make are not reproducible because they add a load of flags to the build that are set when you configure GNUstep Make. And, with dependencies on Foundation, things are not possible to integrate with our testing infrastructure. Is it possible for you to provide a minimal reproducible case? Something with no dependencies outside libobjc2 and with all of the command-line flags that you provide?

From the provided files, I can't tell which ABI you're using. The old GCC ABI had a lot of limitations and I'd expect a crash in this case, the GNUstep 2.0 ABI should have fixed them (but may still contain bugs) and I think the GNUstep 1.0 ABI mostly fixed them but had a few corner cases.

— Reply to this email directly, view it on GitHub https://github.com/gnustep/libobjc2/issues/320#issuecomment-2525676260, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABY5W6N3CL4FDW7QWTONCHL2EQV43AVCNFSM6AAAAABTGLCFGOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKMRVGY3TMMRWGA. You are receiving this because you authored the thread.

lcampbel avatar Dec 10 '24 13:12 lcampbel

I haven't used GNUstep Make for many years, but I think the ng thing means that it will pass --fobjc-runtime=gnustep-2.0. That's the important flag. I might be able to reduce your test case if I have that, but something that compiles without Foundation would be very helpful.

davidchisnall avatar Dec 10 '24 13:12 davidchisnall