Skip to content

Commit

Permalink
Add C++ exception support for __cxa_rethrow (#3996)
Browse files Browse the repository at this point in the history
I have added custom calls that can be later used by Unity SDK for capturing C++ exceptions on iOS.
Also, when the current exception is NULL (during the std::terminate call) the sentrycrashsc_initSelfThread call is made to enrich the stack trace.

Co-authored-by: Philipp Hofmann <philipp.hofmann@sentry.io>
  • Loading branch information
munkiki7 and philipphofmann authored May 22, 2024
1 parent b11cd87 commit cf97209
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 34 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Features

- Add C++ exception support for `__cxa_rethrow` (#3996)

### Improvements

- Stop FramesTracker when app is in background (#3979)
Expand Down
34 changes: 23 additions & 11 deletions Samples/macOS-Swift/macOS-Swift/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="19455" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="19455"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22690"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
Expand Down Expand Up @@ -711,10 +711,10 @@
<autoresizingMask key="autoresizingMask"/>
<subviews>
<stackView distribution="fill" orientation="vertical" alignment="centerX" spacing="12" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" fixedFrame="YES" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fsa-9g-bf3">
<rect key="frame" x="161" y="59" width="164" height="244"/>
<rect key="frame" x="161" y="27" width="224" height="276"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="nAm-U5-PON">
<rect key="frame" x="14" y="217" width="136" height="32"/>
<rect key="frame" x="44" y="249" width="136" height="32"/>
<buttonCell key="cell" type="push" title="Add Breadcrumb" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="zk9-d6-mm1">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
Expand All @@ -724,7 +724,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="dzU-Gi-2VZ">
<rect key="frame" x="12" y="185" width="141" height="32"/>
<rect key="frame" x="42" y="217" width="141" height="32"/>
<buttonCell key="cell" type="push" title="Capture Message" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="EQH-kc-eDD">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
Expand All @@ -734,7 +734,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Ocz-Nk-ZQ2">
<rect key="frame" x="-7" y="153" width="178" height="32"/>
<rect key="frame" x="23" y="185" width="178" height="32"/>
<buttonCell key="cell" type="push" title="Capture User Feedback" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="nui-gg-F5o">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
Expand All @@ -744,7 +744,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="GQW-jy-1TZ">
<rect key="frame" x="4" y="121" width="156" height="32"/>
<rect key="frame" x="34" y="153" width="156" height="32"/>
<buttonCell key="cell" type="push" title="_crashOnException:" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="7rF-ep-EYR">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
Expand All @@ -754,7 +754,7 @@
</buttonCell>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="c5W-zA-19P">
<rect key="frame" x="7" y="89" width="150" height="32"/>
<rect key="frame" x="37" y="121" width="150" height="32"/>
<buttonCell key="cell" type="push" title="captureTransaction" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="OVU-vi-LRM">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
Expand All @@ -764,7 +764,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="0rS-ee-VAF">
<rect key="frame" x="22" y="57" width="120" height="32"/>
<rect key="frame" x="52" y="89" width="120" height="32"/>
<buttonCell key="cell" type="push" title="Sentry.crash()" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="k1V-IH-Ru7">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
Expand All @@ -774,7 +774,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="sxu-g3-vT7" userLabel="CppException">
<rect key="frame" x="21" y="25" width="123" height="32"/>
<rect key="frame" x="51" y="57" width="123" height="32"/>
<buttonCell key="cell" type="push" title="CPP Exception" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="B4S-qm-cMV">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
Expand All @@ -783,8 +783,18 @@
<action selector="cppException:" target="XfG-lQ-9wD" id="mIk-IE-HEb"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Cfu-21-l6L" userLabel="CppException">
<rect key="frame" x="-7" y="25" width="238" height="32"/>
<buttonCell key="cell" type="push" title="Rethrow No Active CPP Exception" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="YRN-qy-qrz">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<connections>
<action selector="rethrowNoActiveCppException:" target="XfG-lQ-9wD" id="fGo-DY-Pj9"/>
</connections>
</buttonCell>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="onh-qf-HCq" userLabel="asyncCrash">
<rect key="frame" x="29" y="-7" width="107" height="32"/>
<rect key="frame" x="59" y="-7" width="107" height="32"/>
<buttonCell key="cell" type="push" title="async crash" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="3ec-oQ-wXv">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
Expand All @@ -803,6 +813,7 @@
<integer value="1000"/>
<integer value="1000"/>
<integer value="1000"/>
<integer value="1000"/>
</visibilityPriorities>
<customSpacing>
<real value="3.4028234663852886e+38"/>
Expand All @@ -813,6 +824,7 @@
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
</customSpacing>
</stackView>
</subviews>
Expand Down
8 changes: 8 additions & 0 deletions Samples/macOS-Swift/macOS-Swift/CppSample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,11 @@ Sentry::CppSample::throwCPPException(void)
{
internalFunction();
}

void
Sentry::CppSample::rethrowNoActiveCPPException(void)
{
// Rethrowing an exception when there is no active exception will lead to std::terminate being
// called.
throw;
}
1 change: 1 addition & 0 deletions Samples/macOS-Swift/macOS-Swift/CppSample.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace Sentry {
class CppSample {
public:
void throwCPPException();
void rethrowNoActiveCPPException();
};
}

Expand Down
1 change: 1 addition & 0 deletions Samples/macOS-Swift/macOS-Swift/CppWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@

@interface CppWrapper : NSObject
- (void)throwCPPException;
- (void)rethrowNoActiveCPPException;
@end
6 changes: 6 additions & 0 deletions Samples/macOS-Swift/macOS-Swift/CppWrapper.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,10 @@ - (void)throwCPPException
cppTool.throwCPPException();
}

- (void)rethrowNoActiveCPPException
{
Sentry::CppSample cppTool;
cppTool.rethrowNoActiveCPPException();
}

@end
4 changes: 4 additions & 0 deletions Samples/macOS-Swift/macOS-Swift/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ class ViewController: NSViewController {
wrapper.throwCPPException()
}

@IBAction func rethrowNoActiveCppException(_ sender: Any) {
let wrapper = CppWrapper()
wrapper.rethrowNoActiveCPPException()
}
@IBAction func asyncCrash(_ sender: Any) {
DispatchQueue.main.async {
self.asyncCrash1()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ static SentryCrashStackCursor g_stackCursor;
// ============================================================================

typedef void (*cxa_throw_type)(void *, std::type_info *, void (*)(void *));
typedef void (*cxa_rethrow_type)(void);

extern "C" {
void __cxa_throw(void *thrown_exception, std::type_info *tinfo, void (*dest)(void *))
Expand All @@ -92,6 +93,28 @@ __cxa_throw(void *thrown_exception, std::type_info *tinfo, void (*dest)(void *))
orig_cxa_throw(thrown_exception, tinfo, dest);
__builtin_unreachable();
}

void
__sentry_cxa_throw(void *thrown_exception, std::type_info *tinfo, void (*dest)(void *))
{
__cxa_throw(thrown_exception, tinfo, dest);
}

void
__sentry_cxa_rethrow()
{
if (g_captureNextStackTrace) {
sentrycrashsc_initSelfThread(&g_stackCursor, 1);
}

static cxa_rethrow_type orig_cxa_rethrow = NULL;
unlikely_if(orig_cxa_rethrow == NULL)
{
orig_cxa_rethrow = (cxa_rethrow_type)dlsym(RTLD_NEXT, "__cxa_rethrow");
}
orig_cxa_rethrow();
__builtin_unreachable();
}
}

void
Expand Down Expand Up @@ -127,33 +150,39 @@ CPPExceptionTerminate(void)
const char *description = descriptionBuff;
descriptionBuff[0] = 0;

SentryCrashLOG_DEBUG("Discovering what kind of exception was thrown.");
g_captureNextStackTrace = false;
try {
throw;
} catch (std::exception &exc) {
strncpy(descriptionBuff, exc.what(), sizeof(descriptionBuff));
}
std::exception_ptr currException = std::current_exception();
if (currException == NULL) {
SentryCrashLOG_DEBUG("Terminate without exception.");
sentrycrashsc_initSelfThread(&g_stackCursor, 0);
} else {
SentryCrashLOG_DEBUG("Discovering what kind of exception was thrown.");
g_captureNextStackTrace = false;
try {
throw;
} catch (std::exception &exc) {
strncpy(descriptionBuff, exc.what(), sizeof(descriptionBuff));
}
#define CATCH_VALUE(TYPE, PRINTFTYPE) \
catch (TYPE value) { \
snprintf(descriptionBuff, sizeof(descriptionBuff), "%" #PRINTFTYPE, value); \
}
CATCH_VALUE(char, d)
CATCH_VALUE(short, d)
CATCH_VALUE(int, d)
CATCH_VALUE(long, ld)
CATCH_VALUE(long long, lld)
CATCH_VALUE(unsigned char, u)
CATCH_VALUE(unsigned short, u)
CATCH_VALUE(unsigned int, u)
CATCH_VALUE(unsigned long, lu)
CATCH_VALUE(unsigned long long, llu)
CATCH_VALUE(float, f)
CATCH_VALUE(double, f)
CATCH_VALUE(long double, Lf)
CATCH_VALUE(char *, s)
catch (...) { description = NULL; }
g_captureNextStackTrace = g_isEnabled;
CATCH_VALUE(char, d)
CATCH_VALUE(short, d)
CATCH_VALUE(int, d)
CATCH_VALUE(long, ld)
CATCH_VALUE(long long, lld)
CATCH_VALUE(unsigned char, u)
CATCH_VALUE(unsigned short, u)
CATCH_VALUE(unsigned int, u)
CATCH_VALUE(unsigned long, lu)
CATCH_VALUE(unsigned long long, llu)
CATCH_VALUE(float, f)
CATCH_VALUE(double, f)
CATCH_VALUE(long double, Lf)
CATCH_VALUE(char *, s)
catch (...) { description = NULL; }
g_captureNextStackTrace = g_isEnabled;
}

// TODO: Should this be done here? Maybe better in the exception
// handler?
Expand Down

0 comments on commit cf97209

Please sign in to comment.