Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
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

- Auto-suppress `SIGABRT` for uncaught managed exceptions on iOS ([#4523](https://github.com/getsentry/sentry-dotnet/pull/4523))

### Fixes

- Fail when building Blazor WASM with Profiling. We don't support profiling in Blazor WebAssembly projects. ([#4512](https://github.com/getsentry/sentry-dotnet/pull/4512))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ internal void Handle(object sender, MarshalManagedExceptionEventArgs e)

if (e.Exception is { } ex)
{
// The Obj-C runtime is about to abort. Tag the upcoming duplicate native SIGABRT event for filtering it
// out in ProcessOnBeforeSend.
// TODO: define "_captured_by_sentry-dotnet" as a constant somewhere
SentryCocoaSdk.ConfigureScope(scope => scope.SetTagValue("SIGABRT", "_captured_by_sentry-dotnet"));

ex.SetSentryMechanism(
"Runtime.MarshalManagedException",
"This exception was caught by the .NET Runtime Marshal Managed Exception global error handler. " +
Expand Down
3 changes: 2 additions & 1 deletion src/Sentry/Platforms/Cocoa/SentryOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -207,11 +207,12 @@ internal NativeOptions(SentryOptions options)
/// convenient.
/// </para>
/// <para>
/// TODO: Explain auto (null) vs. true vs. false.
/// Enabling this may prevent the capture of SIGABRT originating from native (not managed) code... so it may
/// prevent the capture of genuine native SIGABRT errors.
/// </para>
/// </summary>
public bool SuppressSignalAborts { get; set; } = false;
public bool? SuppressSignalAborts { get; set; } = null;

/// <summary>
/// <para>
Expand Down
22 changes: 15 additions & 7 deletions src/Sentry/Platforms/Cocoa/SentrySdk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,25 +200,28 @@ private static CocoaSdk.SentryHttpStatusCodeRange[] GetFailedRequestStatusCodes(
/// </summary>
internal static CocoaSdk.SentryEvent? ProcessOnBeforeSend(SentryOptions options, CocoaSdk.SentryEvent evt, IHub hub)
{
if (hub is DisabledHub)
{
return evt;
}

// When we have an unhandled managed exception, we send that to Sentry twice - once managed and once native.
// The managed exception is what a .NET developer would expect, and it is sent by the Sentry.NET SDK
// But we also get a native SIGABRT since it crashed the application, which is sent by the Sentry Cocoa SDK.

// There should only be one exception on the event in this case
if ((options.Native.SuppressSignalAborts || options.Native.SuppressExcBadAccess) && evt.Exceptions?.Length == 1)
if (evt.Exceptions?.Length == 1)
{
// It will match the following characteristics
var ex = evt.Exceptions[0];

// TODO: define "_captured_by_sentry-dotnet" as a constant somewhere
if (options.Native.SuppressSignalAborts == null && ex.Type == evt.Tags?["_captured_by_sentry-dotnet"]?.ToString())
{
options.LogDebug("Discarded {0} error ({1}). Captured as managed exception instead.", ex.Type,
ex.Value);
return null;
}

// Thankfully, sometimes we can see Xamarin's unhandled exception handler on the stack trace, so we can filter
// them out. Here is the function that calls abort(), which we will use as a filter:
// https://github.com/xamarin/xamarin-macios/blob/c55fbdfef95028ba03d0f7a35aebca03bd76f852/runtime/runtime.m#L1114-L1122
if (options.Native.SuppressSignalAborts && ex.Type == "SIGABRT" && ex.Value == "Signal 6, Code 0" &&
if (options.Native.SuppressSignalAborts == true && ex.Type == "SIGABRT" && ex.Value == "Signal 6, Code 0" &&
ex.Stacktrace?.Frames.Any(f => f.Function == "xamarin_unhandled_exception_handler") is true)
{
// Don't send it
Expand All @@ -239,6 +242,11 @@ private static CocoaSdk.SentryHttpStatusCodeRange[] GetFailedRequestStatusCodes(
}
}

if (hub is DisabledHub)
{
return evt;
}

// We run our SIGABRT checks first before running managed processors.
// Because we delegate to user code, we need to catch/log exceptions.
try
Expand Down
Loading