@@ -195,15 +195,15 @@ private static CocoaSdk.SentryHttpStatusCodeRange[] GetFailedRequestStatusCodes(
195
195
=> ProcessOnBeforeSend ( options , evt , CurrentHub ) ;
196
196
197
197
/// <summary>
198
- /// This overload allows us to inject an IHub for testing. During normal execution, the CurrentHub is used.
199
- /// However, since this class is static, there's no easy alternative way to inject this when executing tests.
198
+ /// Apply suppression logic for redundant native `SIGABRT` and `EXC_BAD_ACCESS` crash events
199
+ /// that have already been captured as managed exceptions by the Sentry.NET SDK to avoid sending
200
+ /// duplicate events to Sentry - once managed and once native.
201
+ ///
202
+ /// The managed exception is what a .NET developer would expect, and it is sent by the Sentry.NET SDK
203
+ /// But we also get a native SIGABRT since it crashed the application, which is sent by the Sentry Cocoa SDK.
200
204
/// </summary>
201
- internal static CocoaSdk . SentryEvent ? ProcessOnBeforeSend ( SentryOptions options , CocoaSdk . SentryEvent evt , IHub hub )
205
+ private static bool SuppressNativeCrash ( SentryOptions options , CocoaSdk . SentryEvent evt )
202
206
{
203
- // When we have an unhandled managed exception, we send that to Sentry twice - once managed and once native.
204
- // The managed exception is what a .NET developer would expect, and it is sent by the Sentry.NET SDK
205
- // But we also get a native SIGABRT since it crashed the application, which is sent by the Sentry Cocoa SDK.
206
-
207
207
// There should only be one exception on the event in this case
208
208
if ( ( options . Native . SuppressSignalAborts || options . Native . SuppressExcBadAccess ) && evt . Exceptions ? . Length == 1 )
209
209
{
@@ -219,7 +219,7 @@ private static CocoaSdk.SentryHttpStatusCodeRange[] GetFailedRequestStatusCodes(
219
219
// Don't send it
220
220
options . LogDebug ( "Discarded {0} error ({1}). Captured as managed exception instead." , ex . Type ,
221
221
ex . Value ) ;
222
- return null ! ;
222
+ return true ;
223
223
}
224
224
225
225
// Similar workaround for NullReferenceExceptions. We don't have any easy way to know whether the
@@ -230,10 +230,28 @@ private static CocoaSdk.SentryHttpStatusCodeRange[] GetFailedRequestStatusCodes(
230
230
// Don't send it
231
231
options . LogDebug ( "Discarded {0} error ({1}). Captured as managed exception instead." , ex . Type ,
232
232
ex . Value ) ;
233
- return null ! ;
233
+ return true ;
234
234
}
235
235
}
236
236
237
+ return false ;
238
+ }
239
+
240
+ /// <summary>
241
+ /// This overload allows us to inject an IHub for testing. During normal execution, the CurrentHub is used.
242
+ /// However, since this class is static, there's no easy alternative way to inject this when executing tests.
243
+ /// </summary>
244
+ internal static CocoaSdk . SentryEvent ? ProcessOnBeforeSend ( SentryOptions options , CocoaSdk . SentryEvent evt , IHub hub )
245
+ {
246
+ // Redundant native crash events must be suppressed even if the SDK is
247
+ // disabled (or not yet fully initialized) to avoid sending duplicates.
248
+ // https://github.com/getsentry/sentry-dotnet/pull/4521#discussion_r2347616896
249
+ if ( SuppressNativeCrash ( options , evt ) )
250
+ {
251
+ return null ! ;
252
+ }
253
+
254
+ // If the SDK is disabled, there are no event processors or before send to run.
237
255
if ( hub is DisabledHub )
238
256
{
239
257
return evt ;
0 commit comments