[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
>
- Re: Crash occurs when catching std::exception in Objective-C++ code compiled with clang on Linux and using libobjc2, David Chisnall, 2017/11/01
- Re: Crash occurs when catching std::exception in Objective-C++ code compiled with clang on Linux and using libobjc2,
Lobron, David <=
- Re: Crash occurs when catching std::exception in Objective-C++ code compiled with clang on Linux and using libobjc2, Lobron, David, 2017/11/16
- Re: Crash occurs when catching std::exception in Objective-C++ code compiled with clang on Linux and using libobjc2, David Chisnall, 2017/11/16
- Re: Crash occurs when catching std::exception in Objective-C++ code compiled with clang on Linux and using libobjc2, Lobron, David, 2017/11/16
- Re: Crash occurs when catching std::exception in Objective-C++ code compiled with clang on Linux and using libobjc2, Lobron, David, 2017/11/16
- Re: Crash occurs when catching std::exception in Objective-C++ code compiled with clang on Linux and using libobjc2, David Chisnall, 2017/11/17
- Re: Crash occurs when catching std::exception in Objective-C++ code compiled with clang on Linux and using libobjc2, Lobron, David, 2017/11/17
- Re: Crash occurs when catching std::exception in Objective-C++ code compiled with clang on Linux and using libobjc2, David Chisnall, 2017/11/17
- Re: Crash occurs when catching std::exception in Objective-C++ code compiled with clang on Linux and using libobjc2, Lobron, David, 2017/11/17
- Re: Crash occurs when catching std::exception in Objective-C++ code compiled with clang on Linux and using libobjc2, David Chisnall, 2017/11/18