Skip to content

Commit 63dc0ce

Browse files
committed
Merge branch 'main' into 2710-macos_version
2 parents f8c2acd + 19b5a7e commit 63dc0ce

File tree

10 files changed

+186
-8
lines changed

10 files changed

+186
-8
lines changed

.github/workflows/codeql-analysis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ jobs:
3535
uses: ./.github/actions/environment
3636

3737
- name: Initialize CodeQL
38-
uses: github/codeql-action/init@dd746615b3b9d728a6a37ca2045b68ca76d4841a # pin@v2
38+
uses: github/codeql-action/init@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # pin@v2
3939
with:
4040
languages: csharp
4141

@@ -49,6 +49,6 @@ jobs:
4949
run: dotnet build Sentry-CI-CodeQL.slnf --no-restore --nologo
5050

5151
- name: Perform CodeQL Analysis
52-
uses: github/codeql-action/analyze@dd746615b3b9d728a6a37ca2045b68ca76d4841a # pin@v2
52+
uses: github/codeql-action/analyze@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # pin@v2
5353
with:
5454
category: '/language:csharp'

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
steps:
2121
- name: Get auth token
2222
id: token
23-
uses: actions/create-github-app-token@136412a57a7081aa63c935a2cc2918f76c34f514 # v1.11.2
23+
uses: actions/create-github-app-token@67e27a7eb7db372a1c61a7f9bdab8699e9ee57f7 # v1.11.3
2424
with:
2525
app-id: ${{ vars.SENTRY_RELEASE_BOT_CLIENT_ID }}
2626
private-key: ${{ secrets.SENTRY_RELEASE_BOT_PRIVATE_KEY }}

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,17 @@
44

55
### Fixes
66

7+
- Native SIGSEGV errors resulting from managed NullReferenceExceptions are now suppressed on Android ([#3903](https://github.com/getsentry/sentry-dotnet/pull/3903))
78
- OTel activities that are marked as not recorded are no longer sent to Sentry ([#3890](https://github.com/getsentry/sentry-dotnet/pull/3890))
89
- Fixed envelopes with oversized attachments getting stuck in __processing ([#3938](https://github.com/getsentry/sentry-dotnet/pull/3938))
910
- Unknown stack frames in profiles on .NET 8+ ([#3942](https://github.com/getsentry/sentry-dotnet/pull/3942))
1011
- Deduplicate profiling stack frames ([#3941](https://github.com/getsentry/sentry-dotnet/pull/3941))
1112
- OperatingSystem will now return macOS as OS name instead of 'Darwin' as well as the proper version. ([#2710](https://github.com/getsentry/sentry-dotnet/pull/3956))
13+
- Ignore null value on CocoaScopeObserver.SetTag ([#3948](https://github.com/getsentry/sentry-dotnet/pull/3948))
1214

1315
## 5.1.0
1416

1517
### Significant change in behavior
16-
1718
- The User.IpAddress is now only set to `{{auto}}` when `SendDefaultPii` is enabled. This change gives you control over IP address collection directly on the client ([#3893](https://github.com/getsentry/sentry-dotnet/pull/3893))
1819

1920
### Features

src/Sentry/Http/HttpTransportBase.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ private void ExtractRateLimits(HttpHeaders responseHeaders)
271271

272272
// Join to a string to handle both single-header and multi-header cases
273273
var rateLimitsEncoded = string.Join(",", rateLimitHeaderValues);
274+
_options.LogDebug("Parsing rate limit headers: {0}", rateLimitsEncoded);
274275

275276
// Parse and order by retry-after so that the longer rate limits are set last (and not overwritten)
276277
var rateLimits = RateLimit.ParseMany(rateLimitsEncoded).OrderBy(rl => rl.RetryAfter);

src/Sentry/Platforms/Android/AndroidOptions.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,21 @@ public class AndroidOptions
2525
/// </summary>
2626
/// <seealso cref="LogCatIntegration" />
2727
public int LogCatMaxLines { get; set; } = 1000;
28+
29+
/// <summary>
30+
/// <para>
31+
/// Whether to suppress capturing SIGSEGV (Segfault) errors in the Native SDK.
32+
/// </para>
33+
/// <para>
34+
/// When managed code results in a NullReferenceException, this also causes a SIGSEGV (Segfault). Duplicate
35+
/// events (one managed and one native) can be prevented by suppressing native Segfaults, which may be
36+
/// convenient.
37+
/// </para>
38+
/// <para>
39+
/// Enabling this may prevent the capture of Segfault originating from native (not managed) code... so it may
40+
/// prevent the capture of genuine native Segfault errors.
41+
/// </para>
42+
/// </summary>
43+
public bool SuppressSegfaults { get; set; } = false;
2844
}
2945
}

src/Sentry/Platforms/Android/BindableAndroidSentryOptions.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ public class AndroidOptions
1414
{
1515
public LogCatIntegrationType? LogCatIntegration { get; set; }
1616
public int? LogCatMaxLines { get; set; }
17+
public bool? SuppressSegfaults { get; set; }
1718

1819
public void ApplyTo(SentryOptions.AndroidOptions options)
1920
{
2021
options.LogCatIntegration = LogCatIntegration ?? options.LogCatIntegration;
2122
options.LogCatMaxLines = LogCatMaxLines ?? options.LogCatMaxLines;
23+
options.SuppressSegfaults = SuppressSegfaults ?? options.SuppressSegfaults;
2224
}
2325
}
2426
}

src/Sentry/Platforms/Android/SentrySdk.cs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Sentry.Android;
44
using Sentry.Android.Callbacks;
55
using Sentry.Android.Extensions;
6+
using Sentry.Extensibility;
67
using Sentry.JavaSdk.Android.Core;
78

89
// Don't let the Sentry Android SDK auto-init, as we do that manually in SentrySdk.Init
@@ -99,10 +100,7 @@ private static void InitSentryAndroidSdk(SentryOptions options)
99100
}
100101
}
101102

102-
if (options.Native.EnableBeforeSend && options.BeforeSendInternal is { } beforeSend)
103-
{
104-
o.BeforeSend = new BeforeSendCallback(beforeSend, options, o);
105-
}
103+
o.BeforeSend = new BeforeSendCallback(BeforeSendWrapper(options), options, o);
106104

107105
// These options are from SentryAndroidOptions
108106
o.AttachScreenshot = options.Native.AttachScreenshot;
@@ -172,6 +170,26 @@ private static void InitSentryAndroidSdk(SentryOptions options)
172170
// TODO: Pause/Resume
173171
}
174172

173+
internal static Func<SentryEvent, SentryHint, SentryEvent?> BeforeSendWrapper(SentryOptions options)
174+
{
175+
return (evt, hint) =>
176+
{
177+
// Suppress SIGSEGV errors.
178+
// See: https://github.com/getsentry/sentry-dotnet/pull/3903
179+
if (options.Android.SuppressSegfaults
180+
&& evt.SentryExceptions?.FirstOrDefault() is { Type: "SIGSEGV", Value: "Segfault" })
181+
{
182+
options.LogDebug("Suppressing SIGSEGV (this will be thrown as a managed exception instead)");
183+
return null;
184+
}
185+
186+
// Call the user defined BeforeSend callback, if it's defined - otherwise return the event as-is
187+
return (options.Native.EnableBeforeSend && options.BeforeSendInternal is { } beforeSend)
188+
? beforeSend(evt, hint)
189+
: evt;
190+
};
191+
}
192+
175193
private static void AndroidEnvironment_UnhandledExceptionRaiser(object? _, RaiseThrowableEventArgs e)
176194
{
177195
var description = "This exception was caught by the Android global error handler.";

src/Sentry/Platforms/Cocoa/CocoaScopeObserver.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ public void SetExtra(string key, object? value)
6767

6868
public void SetTag(string key, string value)
6969
{
70+
if (value is null)
71+
{
72+
_options.LogDebug("Tag with key '{0}' was null. Use Unset to remove tags instead.", key);
73+
return;
74+
}
75+
7076
try
7177
{
7278
SentryCocoaSdk.ConfigureScope(scope => scope.SetTagValue(value, key));
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
#if ANDROID
2+
namespace Sentry.Tests.Platforms.Android;
3+
4+
public class SentrySdkTests
5+
{
6+
[Fact]
7+
public void BeforeSendWrapper_Suppress_SIGSEGV_ReturnsNull()
8+
{
9+
// Arrange
10+
var options = new SentryOptions();
11+
options.Android.SuppressSegfaults = true;
12+
var evt = new SentryEvent
13+
{
14+
SentryExceptions = new[]
15+
{
16+
new SentryException
17+
{
18+
Type = "SIGSEGV",
19+
Value = "Segfault"
20+
}
21+
}
22+
};
23+
var hint = new SentryHint();
24+
25+
// Act
26+
var result = SentrySdk.BeforeSendWrapper(options).Invoke(evt, hint);
27+
28+
// Assert
29+
result.Should().BeNull();
30+
}
31+
32+
[Fact]
33+
public void BeforeSendWrapper_DontSupress_SIGSEGV_ReturnsEvent()
34+
{
35+
// Arrange
36+
var options = new SentryOptions();
37+
options.Android.SuppressSegfaults = false;
38+
var evt = new SentryEvent
39+
{
40+
SentryExceptions = new[]
41+
{
42+
new SentryException
43+
{
44+
Type = "SIGSEGV",
45+
Value = "Segfault"
46+
}
47+
}
48+
};
49+
var hint = new SentryHint();
50+
51+
// Act
52+
var result = SentrySdk.BeforeSendWrapper(options).Invoke(evt, hint);
53+
54+
// Assert
55+
result.Should().Be(evt);
56+
}
57+
58+
[Fact]
59+
public void BeforeSendWrapper_BeforeSendCallbackDefined_CallsBeforeSend()
60+
{
61+
// Arrange
62+
var beforeSend = Substitute.For<Func<SentryEvent, SentryHint, SentryEvent>>();
63+
beforeSend.Invoke(Arg.Any<SentryEvent>(), Arg.Any<SentryHint>()).Returns(callInfo => callInfo.Arg<SentryEvent>());
64+
65+
var options = new SentryOptions();
66+
options.Native.EnableBeforeSend = true;
67+
options.SetBeforeSend(beforeSend);
68+
var evt = new SentryEvent();
69+
var hint = new SentryHint();
70+
71+
// Act
72+
var result = SentrySdk.BeforeSendWrapper(options).Invoke(evt, hint);
73+
74+
// Assert
75+
beforeSend.Received(1).Invoke(Arg.Any<SentryEvent>(), Arg.Any<SentryHint>());
76+
result.Should().Be(evt);
77+
}
78+
79+
[Fact]
80+
public void BeforeSendWrapper_NoBeforeSendCallback_ReturnsEvent()
81+
{
82+
// Arrange
83+
var options = new SentryOptions();
84+
options.Native.EnableBeforeSend = true;
85+
var evt = new SentryEvent();
86+
var hint = new SentryHint();
87+
88+
// Act
89+
var result = SentrySdk.BeforeSendWrapper(options).Invoke(evt, hint);
90+
91+
// Assert
92+
result.Should().Be(evt);
93+
}
94+
95+
[Fact]
96+
public void BeforeSendWrapper_NativeBeforeSendDisabled_ReturnsEvent()
97+
{
98+
// Arrange
99+
var beforeSend = Substitute.For<Func<SentryEvent, SentryHint, SentryEvent>>();
100+
beforeSend.Invoke(Arg.Any<SentryEvent>(), Arg.Any<SentryHint>()).Returns(_ => null);
101+
102+
var options = new SentryOptions();
103+
options.SetBeforeSend(beforeSend);
104+
options.Native.EnableBeforeSend = false;
105+
var evt = new SentryEvent();
106+
var hint = new SentryHint();
107+
108+
// Act
109+
var result = SentrySdk.BeforeSendWrapper(options).Invoke(evt, hint);
110+
111+
// Assert
112+
beforeSend.DidNotReceive().Invoke(Arg.Any<SentryEvent>(), Arg.Any<SentryHint>());
113+
result.Should().Be(evt);
114+
}
115+
}
116+
#endif

test/Sentry.Tests/ScopeTests.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,24 @@ public void Filtered_tags_are_not_set()
615615

616616
scope.Tags.Should().OnlyContain(pair => pair.Key == "AzFunctions" && pair.Value == "rule");
617617
}
618+
619+
[Fact]
620+
public void SetTag_NullValue_DoesNotThrowArgumentNullException()
621+
{
622+
var scope = new Scope();
623+
624+
ArgumentNullException exception = null;
625+
try
626+
{
627+
scope.SetTag("IAmNull", null);
628+
}
629+
catch (ArgumentNullException e)
630+
{
631+
exception = e;
632+
}
633+
634+
Assert.Null(exception);
635+
}
618636
}
619637

620638
public static class ScopeTestExtensions

0 commit comments

Comments
 (0)