discuss-gnustep
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Crash occurs when catching std::exception in Objective-C++ code comp


From: Lobron, David
Subject: Re: Crash occurs when catching std::exception in Objective-C++ code compiled with clang on Linux and using libobjc2
Date: Wed, 1 Nov 2017 14:11:42 +0000

Thanks very much, David- this is extremely helpful!  As you might expect, my 
code was running perfectly on the Mac, but crashing on Linux- this explains 
both.

Just to make sure I understand, can you tell me exactly where to specify 
-fobjc-runtime=gnustep-1.8?  Would that be an argument when building 
llvm/clang, or libobjc2, or both?

Thank you,

David

> On Nov 1, 2017, at 4:25 AM, David Chisnall <theraven@sucs.org> wrote:
> 
> Hi,
> 
> I’m a bit surprised I missed your LLVM mailing list post, because I am the 
> maintainer of the relevant clang code, as well as of libobjc2.  If you had 
> asked me earlier, I could have saved you a lot of time:
> 
> This test case works perfectly for me on FreeBSD, where clang defaults to 
> -fobjc-runtime=gnustep.  It segfaults if I add -fobjc-runtime=gcc.  This is 
> entirely expected, because the GCC ABI for exceptions is makes it impossible 
> to correctly interop with C++ (I spent a few weeks trying and it always fails 
> for at least some of the corner cases).  If you specify 
> -fobjc-runtime=gnustep-1.8, then it will work correctly.
> 
> When using the GNUstep ABI, Objective-C objects are thrown as Objective-C 
> exceptions, C++ objects are thrown as C++ exceptions.  The GNUstep ObjC++ 
> personality function is used for catch and @catch blocks in ObjC++ code, the 
> ObjC personality function for @catch blocks in ObjC code, and the C++ 
> personality function in C++ code.  The C++ and ObjC personality functions 
> don’t let you catch foreign exceptions (except for cleanups or with catch(…) 
> in C++).  The ObjC++ personality function checks whether the thrown exception 
> is from C++ or ObjC.  If it’s thrown from C++, it simply forwards it to the 
> C++ personality function.  If it’s thrown from ObjC, then it wraps it in a 
> C++ exception first, and provides some special C++ type_info structures that 
> allow the C++ personality function to deliver it to the correct block.  This 
> allows us to use a slightly more efficient code path for pure-ObjC exceptions.
> 
> The Apple implementation simply implements the ObjC exceptions as thin 
> wrappers around C++ exceptions, so ObjC exceptions are always thrown as C++ 
> exceptions.  This means that the Apple ObjC runtime has a hard dependency on 
> their C++ runtime, even when not using ObjC++.  This doesn’t matter too much 
> for them, because a bunch of their core frameworks are C++ or ObjC++, so 
> there’s likely not to be any code on macOS / iOS that uses ObjC but not C++.
> 
> Note: We have tests for all of these cases in the libobjc2 test suite.  
> There’s also some logic to allow foreign exceptions to be automatically boxed 
> as ObjC objects.
> 
> David
> 
>> On 31 Oct 2017, at 20:13, Lobron, David <dlobron@akamai.com> wrote:
>> 
>> Hello GNUstep,
>> 
>> I opened a bug with clang/llvm a few months ago when I found that 
>> Objective-C++ programs compiled with clang on Linux were crashing with a 
>> segmentation fault when the code attempted to catch a std::exception.  The 
>> crash only occurred when the code was compiled as Objective-C++ (i.e., with 
>> a suffix of .mm).  When compiled as C++, with a .cc suffix, the code works 
>> correctly.  The code to reproduce the bug is very simple and pure C++:
>> 
>> #include <iostream>
>> 
>> using namespace std;
>> 
>> int main(int argc, char *argv[]) {
>> try {
>>   throw exception();
>> } catch (exception &e) {
>> }
>> 
>> return 0;
>> }
>> 
>> I worked on this with an llvm developer, and he reported the following:
>> 
>> "I've investigated the issue further and discovered that the problem is with 
>> personality routine. For C++ in my case it was 
>> __cxxabiv1::__gxx_personality_v0. It returned _URC_HANDLER_FOUND and 
>> correctly prepared everything to land in the catch block.
>> 
>> For ObjC++ it was __gnu_objc_personality_v0 () from 
>> /usr/lib/x86_64-linux-gnu/libobjc.so.4. In my case it returned 
>> _URC_CONTINUE_UNWIND, so the exception wasn't caught in `main` and it caused 
>> SIGABRT as any uncaught exception does. Personality routine is also 
>> responsible for setting exception object for the catch block so it might be 
>> causing NULL exception object you are observing."
>> 
>> In my own tests, I'm using GNUStep libobjc2, version 1.8.1, which produces a 
>> shared library called libobjc.so.4.6.  My C++ binary has a different 
>> personality from the ObjC++ binary:
>> 
>> C++ (works): __gxx_personality_v0@@CXXABI_1.3
>> ObjC++ (crashes): __gnu_objc_personality_v0
>> 
>> I checked for the string "personality" in libobjc2.so.4.6 using nm, and 
>> found the following matching symbols:
>> 
>> 000000000022e590 d DW.ref.__gcc_personality_v0
>> 000000000022ff08 d DW.ref.__gnustep_objc_personality_v0
>>                U __gcc_personality_v0@@GCC_3.3.1
>> 00000000000126b0 T __gnu_objc_personality_v0
>> 0000000000012d20 T __gnustep_objc_personality_v0
>> 0000000000012d60 T __gnustep_objcxx_personality_v0
>>                w __gxx_personality_v0
>> 00000000000126f0 t internal_objc_personality
>> 
>> I'm a bit suspicious of the "__gcc_personality_v0@@GCC_3.3.1" line, since 
>> I'm compiling with clang rather than gcc.  But that might be a red herring.
>> 
>> The llvm/clang developers suggested I get in touch with GNUstep to see if 
>> this is a known issue.  Has anyone seen this behavior before?
>> 
>> Thanks,
>> 
>> David
>> 
>> 
>> 
>> 
>> 
>> _______________________________________________
>> Discuss-gnustep mailing list
>> Discuss-gnustep@gnu.org
>> https://lists.gnu.org/mailman/listinfo/discuss-gnustep
> 


reply via email to

[Prev in Thread] Current Thread [Next in Thread]