Skip to content
Draft
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
74600ce
feat(objc): Add SentryObjC wrapper SDK and API stability tracking
philprime Mar 4, 2026
2df1ab3
docs(objc): Add comprehensive documentation to SentryObjC wrapper SDK
philprime Mar 10, 2026
bb4bcf2
docs(objc): Document additional SentryObjC data model classes
philprime Mar 10, 2026
50e07e7
docs(objc): Document stack traces and event metadata classes
philprime Mar 10, 2026
2ac98e0
docs(objc): Document session replay and sampling classes
philprime Mar 10, 2026
434212c
wip
philprime Mar 10, 2026
4074c02
ci: Remove file-existence check for sdk_objc_api.json
philprime Mar 10, 2026
59fa2dc
docs(samples): Restore problem description in ObjC-NoModules README
philprime Mar 10, 2026
0e7e483
Merge branch 'main' into philprime/objc-wrapper-sdk-6342
philprime Mar 10, 2026
7b315e6
ref(objc): Rewrite API extraction using clang AST and bash
philprime Mar 10, 2026
96cd092
ci: Add iOS-ObjectiveCpp-NoModules sample to build matrix
philprime Mar 10, 2026
16d4dea
update public API
philprime Mar 10, 2026
bf8a253
Merge branch 'main' into philprime/objc-wrapper-sdk-6342
philprime Mar 10, 2026
e5e4882
feat(objc): Add SentryObjC product to Swift 6.1 package manifest
philprime Mar 10, 2026
ba08e46
docs(objc): Add missing documentation to 9 SentryObjC headers
philprime Mar 10, 2026
33dd2c7
fix(objc): Add SentryCppHelper to Swift 6.1 compile-from-source targets
philprime Mar 10, 2026
e4b4486
feat(objc): Implement SentrySDK wrapper for no-modules context
philprime Mar 10, 2026
913cdfd
fix(objc): Keep SentryCppHelper in initial targets array
philprime Mar 10, 2026
e1eebdf
ref(objc): Rename SentrySDK to SentryObjCSDK to avoid naming conflicts
philprime Mar 10, 2026
97f6f13
WIP
philprime Mar 10, 2026
ab571ff
Merge remote-tracking branch 'origin/main' into philprime/objc-wrappe…
philprime Mar 10, 2026
7a81302
WIP
philprime Mar 10, 2026
56bdb7c
WIP
philprime Mar 10, 2026
5cc3e0d
fix(objc): Add explicit @objc name to SentryObjCBridge
philprime Mar 10, 2026
e2a7aa0
fix(objc): Fix thread safety, replay API, and package manifest issues
philprime Mar 10, 2026
6ee408f
WIP
philprime Mar 10, 2026
82bdd16
Merge remote-tracking branch 'origin/main' into philprime/objc-wrappe…
philprime Mar 11, 2026
cff540f
fix(objc): Fix SentryObjC package resolution and CI failures
philprime Mar 11, 2026
8e6c132
Merge branch 'main' into philprime/objc-wrapper-sdk-6342
philprime Mar 11, 2026
5c6380c
ref: Extract getAppStartMeasurement into SentryAppStartMeasurementPro…
philipphofmann Mar 11, 2026
f4293bc
revert: Remove thread safety changes extracted to PR #7672
philprime Mar 11, 2026
9e207fa
fix(objc): Address critical review bot feedback
philprime Mar 11, 2026
1b9dab0
Merge remote-tracking branch 'origin/main' into philprime/objc-wrappe…
philprime Mar 11, 2026
9ecf30b
update sdk json
philprime Mar 11, 2026
74f68ad
update submodule
philprime Mar 11, 2026
beb048f
wip
philprime Mar 11, 2026
2d3b0ce
Merge branch 'main' into philprime/objc-wrapper-sdk-6342
philprime Mar 12, 2026
34ccdb8
Merge remote-tracking branch 'origin/main' into philprime/objc-wrappe…
philprime Mar 17, 2026
91d834c
ref: rename SentryObjC core headers to match SDK naming
philprime Mar 18, 2026
4b6bc65
ref: rename SentryObjC user and context headers
philprime Mar 18, 2026
42bf54e
ref: rename SentryObjC exception and stack headers
philprime Mar 18, 2026
0d1d853
ref: rename SentryObjC tracing headers
philprime Mar 18, 2026
e5e8c71
ref: rename remaining SentryObjC headers
philprime Mar 18, 2026
3b6f320
ref: update umbrella header imports to new names
philprime Mar 18, 2026
e479465
ref: update cross-header imports to new names
philprime Mar 18, 2026
fc356b3
ref: rename SentryObjCSDK class to SentrySDK
philprime Mar 18, 2026
dad81ef
build: update add-sentryobjc-target.rb to include bridge and Sentry d…
philprime Mar 18, 2026
6336858
build: add SentryObjC variant to xcframework build script
philprime Mar 18, 2026
8d92c5e
ref: rename SentryObjC implementation files
philprime Mar 18, 2026
22824e5
ref: rename SentryObjC class and type names
philprime Mar 18, 2026
d44c00f
fix: disambiguate SentryAttributeContent in Swift bridge
philprime Mar 18, 2026
fc4682e
build: move SentryObjCBridge to Sentry target
philprime Mar 18, 2026
acd8515
WIP
philprime Mar 20, 2026
abcc681
build: standalone SentryObjC xcframework via swiftc
philprime Mar 20, 2026
16f9238
feat: add new public headers for Sentry logging and envelope handling
philprime Mar 20, 2026
143a0d6
build: update framework handling in xcframework build script
philprime Mar 20, 2026
6189f81
ci: add SentryObjC xcframework to CI pipeline
philprime Mar 20, 2026
37eade3
Merge remote-tracking branch 'origin/main' into philprime/objc-wrappe…
philprime Apr 22, 2026
9521b48
fix(build): skip SystemConfiguration on watchOS for SentryObjC xcfram…
philprime Apr 22, 2026
5043b1f
chore(api): regenerate sdk_api_objc.json after header renames
philprime Apr 22, 2026
31cd646
feat(objc): expose SentryOptions.experimental as a typed class
philprime Apr 22, 2026
bf8027a
fix(objc): register SentryExperimentalOptions.h as public header
philprime Apr 22, 2026
f4d732b
fix(objc): mark SentryObjC modulemap as framework module
philprime Apr 22, 2026
f7e40e5
ref(objc): drop manual SentryObjC modulemap and let Xcode generate it
philprime Apr 22, 2026
b37e7c5
feat(objc): ship SentryObjC as separate static and dynamic xcframeworks
philprime Apr 22, 2026
f05c5fe
fix(objc): alias public ObjC classes to Swift mangled names
philprime Apr 22, 2026
05ee02e
Merge remote-tracking branch 'origin/main' into philprime/objc-wrappe…
philprime Apr 23, 2026
e20405b
build(spm): match SentryObjC target layout in swift-6.2 manifest
philprime Apr 23, 2026
d8a3411
manual cleanup and fixed Objective-C sample
philprime Apr 24, 2026
3aeab3b
Merge branch 'main' into philprime/objc-wrapper-sdk-6342
philprime Apr 24, 2026
6bbc7b8
feat(objc): introduce SentryObjCTypes target
philprime Apr 24, 2026
bc0702c
fix(objc): use __has_include for SentryObjCTypes imports
philprime Apr 24, 2026
2091b12
chore(ci): remove duplicate Homebrew update
philprime Apr 24, 2026
e12d8c2
build(objc): wire SentryObjCTypes into xcframework release flow
philprime Apr 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/file-filters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,13 @@ run_api_stability_for_prs: &run_api_stability_for_prs
- "scripts/build-xcframework-slice.sh"
- "scripts/assemble-xcframework.sh"
- "scripts/update-api.sh"
- "scripts/extract-objc-api.sh"
- "scripts/ci-diagnostics.sh"

# API files
- "sdk_api.json"
- "sdk_api_sentryswiftui.json"
- "sdk_objc_api.json"
Comment thread
philprime marked this conversation as resolved.
Outdated

# Build configuration
- "Makefile"
Expand Down
13 changes: 13 additions & 0 deletions .github/workflows/api-stability.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ jobs:
run: |
mv sdk_api.json sdk_api_base.json
mv sdk_api_sentryswiftui.json sdk_api_sentryswiftui_base.json
mv sdk_api_objc.json sdk_api_objc_base.json
./scripts/update-api.sh

- name: Diagnose breaking changes for Sentry
Expand Down Expand Up @@ -87,6 +88,18 @@ jobs:
cat sentryswiftui_result.json
exit 1
fi

- name: Diagnose breaking changes for SentryObjC
if: always()
run: |
if diff -q "sdk_api_objc_base.json" "sdk_api_objc.json" > /dev/null; then
echo "No SentryObjC API changes detected."
else
echo "❌ SentryObjC public API changes are detected. If they're intended run "make generate-public-api" and commit the changes."
diff "sdk_api_objc_base.json" "sdk_api_objc.json" || true
exit 1
fi

- name: Run CI Diagnostics
if: failure()
run: ./scripts/ci-diagnostics.sh
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ jobs:
config: Debug
- scheme: iOS-ObjectiveC
config: Debug
- scheme: iOS-ObjectiveCpp-NoModules
config: Debug
- scheme: SPM
config: Debug
- scheme: DistributionSample
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
When building from source with Swift 6.1+ (using `Package@swift-6.1.swift`), you can enable the `NoUIFramework` trait to avoid linking UIKit or AppKit. Use this for command-line tools, headless server contexts, or other environments where UI frameworks are unavailable.
In Xcode 26.4 and later, add the Sentry package as a dependency and the `SentrySPM` product, then enable the `NoUIFramework` trait on the package reference (Package Dependencies β†’ select Sentry β†’ Traits).
- Metric kit app hangs now report a full flamegraph rather than just one stacktrace during the hang. (#7185)
- Add SentryObjC wrapper SDK to provide pure Objective-C compatibility layer that wraps the main Sentry SDK with stable, documented Objective-C interfaces. (#7598)
This SDK is designed for projects that require strict Objective-C compatibility without Swift dependencies.

### Fixes

Expand Down
15 changes: 12 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ build-xcframework-sample:
build-samples: \
build-sample-DistributionSample \
build-sample-iOS-ObjectiveC \
build-sample-iOS-ObjectiveCpp-NoModules \
build-sample-iOS-Swift \
build-sample-iOS-Swift6 \
build-sample-iOS-SwiftUI \
Expand Down Expand Up @@ -324,9 +325,8 @@ build-sample-visionOS-SwiftUI-SPM:

## Build the iOS-ObjectiveCpp-NoModules sample app
#
# Builds the ObjC++ without-modules sample that reproduces #4543.
# This target is expected to FAIL until the pure ObjC SDK wrapper (#6342)
# is implemented. Use it to verify the fix.
# Builds the ObjC++ without-modules sample that uses SentryObjC (#6342).
# Uses #import <SentryObjC/SentryObjC.h> for ObjC++ without -fmodules.
.PHONY: build-sample-iOS-ObjectiveCpp-NoModules
build-sample-iOS-ObjectiveCpp-NoModules:
xcodegen --spec Samples/iOS-ObjectiveCpp-NoModules/iOS-ObjectiveCpp-NoModules.yml
Expand Down Expand Up @@ -816,6 +816,15 @@ analyze:
generate-public-api:
./scripts/update-api.sh

## Generate SentryObjC public API snapshot
#
# Extracts SentryObjC public API from headers to sdk_objc_api.json.
# Use for quick iteration; full API generation runs via generate-public-api.
.PHONY: generate-objc-api
generate-objc-api:
python3 scripts/extract-objc-api.py > sdk_objc_api.json
Comment thread
philprime marked this conversation as resolved.
Outdated
@echo "--> sdk_objc_api.json updated"

# ============================================================================
# VERSION MANAGEMENT
# ============================================================================
Expand Down
24 changes: 23 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ targets += [
name: "SentryObjCInternal",
dependencies: ["SentrySwift"],
path: "Sources",
exclude: ["Sentry/SentryDummyPublicEmptyClass.m", "Sentry/SentryDummyPrivateEmptyClass.m", "Swift", "SentrySwiftUI", "Resources", "Configuration", "SentryCppHelper", "SentryDistribution", "SentryDistributionTests"],
exclude: ["Sentry/SentryDummyPublicEmptyClass.m", "Sentry/SentryDummyPrivateEmptyClass.m", "Swift", "SentrySwiftUI", "Resources", "Configuration", "SentryCppHelper", "SentryDistribution", "SentryDistributionTests", "SentryObjC", "SentryObjCBridge"],
cSettings: [
.headerSearchPath("Sentry"),
.headerSearchPath("SentryCrash/Recording"),
Expand All @@ -107,6 +107,28 @@ targets += [
.headerSearchPath("SentryCrash/Reporting/Filters/Tools")])
]

// Swift bridge that exposes SDK functionality to pure ObjC code (no modules)
products.append(.library(name: "SentryObjC", targets: ["SentryObjCInternal", "SentryObjCBridge", "SentryObjC"]))
targets += [
.target(
name: "SentryObjCBridge",
dependencies: ["SentryObjCInternal"],
path: "Sources/SentryObjCBridge",
swiftSettings: [
.unsafeFlags(["-enable-library-evolution"])
]),

.target(
name: "SentryObjC",
dependencies: ["SentryObjCBridge"],
path: "Sources/SentryObjC",
publicHeadersPath: "Public",
cSettings: [
.headerSearchPath("Public")
]
)
]

let package = Package(
name: "Sentry",
platforms: [.iOS(.v15), .macOS(.v10_14), .tvOS(.v15), .watchOS(.v8), .visionOS(.v1)],
Expand Down
24 changes: 23 additions & 1 deletion Package@swift-6.1.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ targets += [
name: "SentryObjCInternal",
dependencies: ["SentrySwift"],
path: "Sources",
exclude: ["Sentry/SentryDummyPublicEmptyClass.m", "Sentry/SentryDummyPrivateEmptyClass.m", "Swift", "SentrySwiftUI", "Resources", "Configuration", "SentryCppHelper", "SentryDistribution", "SentryDistributionTests"],
exclude: ["Sentry/SentryDummyPublicEmptyClass.m", "Sentry/SentryDummyPrivateEmptyClass.m", "Swift", "SentrySwiftUI", "Resources", "Configuration", "SentryCppHelper", "SentryDistribution", "SentryDistributionTests", "SentryObjC", "SentryObjCBridge"],
cSettings: [
.headerSearchPath("Sentry"),
.headerSearchPath("SentryCrash/Recording"),
Expand All @@ -110,6 +110,28 @@ targets += [
])
]

// Swift bridge that exposes SDK functionality to pure ObjC code (no modules)
products.append(.library(name: "SentryObjC", targets: ["SentryObjCInternal", "SentryObjCBridge", "SentryObjC"]))
targets += [
.target(
name: "SentryObjCBridge",
dependencies: ["SentryObjCInternal"],
path: "Sources/SentryObjCBridge",
swiftSettings: [
.unsafeFlags(["-enable-library-evolution"])
]),

.target(
name: "SentryObjC",
dependencies: ["SentryObjCBridge"],
path: "Sources/SentryObjC",
publicHeadersPath: "Public",
cSettings: [
.headerSearchPath("Public")
]
)
]

let package = Package(
name: "Sentry",
platforms: [.iOS(.v15), .macOS(.v10_14), .tvOS(.v15), .watchOS(.v8), .visionOS(.v1)],
Expand Down
21 changes: 5 additions & 16 deletions Samples/iOS-ObjectiveCpp-NoModules/App/Sources/AppDelegate.mm
Original file line number Diff line number Diff line change
@@ -1,32 +1,21 @@
// Demonstrates the issue from #4543 / #6342: Using Sentry from Objective-C++
// with CLANG_ENABLE_MODULES=NO. We must use #import instead of @import.
//
// With modules disabled, #import <Sentry/Sentry.h> does NOT expose Swift APIs
// (SentrySDK, SentryOptions, options.sessionReplay). We intentionally do NOT
// include Sentry-Swift.h here because that fails with forward declaration
// errors (UIView, UIWindowLevel, etc.) when included from .mm files without
// modules. So we only have #import <Sentry/Sentry.h> and the build fails with
// "use of undeclared identifier 'SentrySDK'" - reproducing the issue.
//
// The sample will NOT build until the pure ObjC SDK wrapper (#6342) is implemented.
// Uses Sentry from Objective-C++ with CLANG_ENABLE_MODULES=NO via the pure
// ObjC wrapper (SentryObjC). Import the umbrella header to access SentrySDK,
// SentryOptions, sessionReplay, etc. without requiring Swift modules.

#import "AppDelegate.h"
#import <Sentry/Sentry.h>
#import <SentryObjC.h>
#import <UIKit/UIKit.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Fails: SentrySDK undeclared - #import <Sentry/Sentry.h> does not expose
// Swift APIs when CLANG_ENABLE_MODULES=NO (SDK 8.54+).
[SentrySDK startWithConfigureOptions:^(SentryOptions *options) {
[SentryObjCSDK startWithConfigureOptions:^(SentryOptions *options) {
options.dsn = @"https://6cc9bae94def43cab8444a99e0031c28@o447951.ingest.sentry.io/5428557";
options.debug = YES;
options.tracesSampleRate = @1.0;

// This fails: options.sessionReplay not exposed without @import
options.sessionReplay.sessionSampleRate = 0;
options.sessionReplay.onErrorSampleRate = 1;
}];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
// Objective-C++ file - same module restrictions as AppDelegate.mm.
// Cannot use @import Sentry here; must use #import.
// No Sentry-Swift.h - would cause forward declaration errors from .mm without modules.
// Objective-C++ file - uses SentryObjC for full SDK access without modules.

#import "ViewController.h"
#import <Sentry/Sentry.h>
#import <SentryObjC.h>
#import <UIKit/UIKit.h>

@implementation ViewController

- (void)viewDidLoad
{
[super viewDidLoad];
// Fails: SentrySDK undeclared with #import alone
[SentrySDK addBreadcrumb:[[SentryBreadcrumb alloc] init]];
[SentryObjCSDK addBreadcrumb:[[SentryBreadcrumb alloc] init]];
}

- (IBAction)captureError:(id)sender
{
NSError *error = [NSError errorWithDomain:@"iOS-ObjectiveCpp-NoModules" code:1 userInfo:nil];
[SentrySDK captureError:error];
[SentryObjCSDK captureError:error];
}

@end
38 changes: 26 additions & 12 deletions Samples/iOS-ObjectiveCpp-NoModules/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# iOS-ObjectiveCpp-NoModules

This sample replicates the issue documented in [getsentry/sentry-cocoa#4543](https://github.com/getsentry/sentry-cocoa/issues/4543): **using the Sentry SDK from Objective-C++ when `-fmodules` and `-fcxx-modules` are not supported.**
This sample demonstrates **using the Sentry SDK from Objective-C++ when `-fmodules` and `-fcxx-modules` are not supported**.

Originally documented the issue in [getsentry/sentry-cocoa#4543](https://github.com/getsentry/sentry-cocoa/issues/4543). Now demonstrates the solution via **SentryObjC**.

## Problem

Expand All @@ -18,21 +20,33 @@ With modules disabled:

**Result:** `SentrySDK`, `SentryOptions`, `options.sessionReplay` and other Swift-bridged APIs are unavailable. The SDK is effectively unusable from ObjC++ without modules.

## This Sample
## Solution: SentryObjC

- Uses **Objective-C++** (`.mm` files) for AppDelegate and ViewController
- Sets **`CLANG_ENABLE_MODULES = NO`** in the build configuration
- Uses only `#import <Sentry/Sentry.h>` in `.mm` files (does **not** import `Sentry-Swift.h`)
- Demonstrates that Swift-bridged APIs like `SentrySDK` and `options.sessionReplay` are unavailable from ObjC++ without modules
The **SentryObjC** product (introduced in [#6342](https://github.com/getsentry/sentry-cocoa/issues/6342)) provides a pure Objective-C wrapper around the main SDK:

```objc
#import <SentryObjC.h> // Pure ObjC - no Swift modules required

**Build status:** The sample **does NOT build** and reproduces the issue. With only `#import <Sentry/Sentry.h>` (no `Sentry-Swift.h`), the compiler reports `error: use of undeclared identifier 'SentrySDK'`. Attempting to include `#import <Sentry/Sentry-Swift.h>` in this setup (see comments in `AppDelegate.mm` / `ViewController.mm`) fails with forward declaration errors when used from `.mm` files without modules. The sample exists to:
[SentryObjCSDK startWithConfigureOptions:^(SentryOptions *options) {
options.dsn = @"...";
options.tracesSampleRate = @1.0;
options.sessionReplay.sessionSampleRate = 0; // All Swift APIs now available!
}];
```

**Key differences from the main Sentry framework:**

1. Document the exact pattern that fails for ObjC++ consumers in production
2. Serve as a test case for the fix in [getsentry/sentry-cocoa#6342](https://github.com/getsentry/sentry-cocoa/issues/6342)
- βœ… Pure Objective-C public interface
- βœ… No Swift modules or `Sentry-Swift.h` required
- βœ… Works in Objective-C++ (`.mm` files) without modules
- βœ… Full access to all SDK features (SentrySDK, SentryOptions, sessionReplay, etc.)

## Planned Fix (#6342)
## This Sample

Issue [#6342](https://github.com/getsentry/sentry-cocoa/issues/6342) proposes a **pure Objective-C SDK wrapper** that can be imported without modules. Once implemented, this sample should build successfully.
- Uses **Objective-C++** (`.mm` files) for AppDelegate and ViewController
- Sets **`CLANG_ENABLE_MODULES = NO`** in the build configuration
- Depends on **SentryObjC** (SPM product) and imports `#import <SentryObjC.h>`
- Builds successfully with full access to SentrySDK, SentryOptions, sessionReplay, etc.

## Generating the Project

Expand All @@ -44,5 +58,5 @@ xcodegen generate
Or from the repo root:

```bash
make xcode-ci # regenerates all sample projects including this one
make build-sample-iOS-ObjectiveCpp-NoModules
```
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
# yaml-language-server: $schema=../../schema/xcodegen.schema.json
#
# This sample replicates the issue from #4543: using Sentry from Objective-C++
# without modules (-fmodules / -fcxx-modules). Many projects (React Native ≀0.76,
# Haxe, custom build systems) cannot enable modules and must use #import instead
# of @import. With CLANG_ENABLE_MODULES=NO, Swift APIs (SentrySDK, sessionReplay,
# etc.) are not available via #import <Sentry/Sentry.h> alone.
#
# This sample does NOT build with the current SDK. It exists to:
# - Document the exact failure mode for ObjC++ consumers
# - Serve as a test case for the fix in #6342 (pure ObjC SDK wrapper)
# This sample uses Sentry from Objective-C++ without modules (-fmodules /
# -fcxx-modules). It depends on SentryObjC, the pure ObjC wrapper that exposes
# the full SDK API via #import <SentryObjC.h>.
#
# See README.md in this directory for details.

Expand All @@ -18,9 +12,9 @@ generateEmptyDirectories: true
configs:
Debug: debug
Release: release
projectReferences:
packages:
Sentry:
path: ../../Sentry.xcodeproj
path: ../..
options:
bundleIdPrefix: io.sentry
targets:
Expand Down Expand Up @@ -58,8 +52,8 @@ targets:
group: App/Configurations
buildPhase: none
dependencies:
- target: Sentry/Sentry
- target: Sentry/SentrySwiftUI
- package: Sentry
product: SentryObjC
configFiles:
Debug: App/Configurations/iOS-ObjectiveCpp-NoModules.xcconfig
Release: App/Configurations/iOS-ObjectiveCpp-NoModules.xcconfig
Expand Down
11 changes: 7 additions & 4 deletions Sources/Sentry/SentryNSExceptionCaptureHelper.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,31 @@
# import "SentryCrash.h"
# import "SentryNSExceptionCaptureHelper.h"
# import "SentrySwift.h"
# import <stdatomic.h>

@implementation SentryNSExceptionCaptureHelper

static BOOL _insideReportException = NO;
// Thread-safe flag to prevent duplicate exception captures when
// _crashOnException: is called from within reportException:
static _Atomic BOOL _insideReportException = NO;

+ (void)reportException:(NSException *)exception
{
_insideReportException = YES;
atomic_store(&_insideReportException, YES);
[self captureException:exception];
}

+ (void)reportExceptionDidFinish
{
_insideReportException = NO;
atomic_store(&_insideReportException, NO);
}

+ (void)crashOnException:(NSException *)exception
{
// When called from within reportException: (i.e., [super reportException:] internally
// dispatches to _crashOnException: when NSApplicationCrashOnExceptions is YES),
// the exception was already captured, so skip to avoid duplicate reports.
if (!_insideReportException) {
if (!atomic_load(&_insideReportException)) {
[self captureException:exception];
}
}
Expand Down
Loading
Loading