Skip to content

Commit e5df035

Browse files
jpnurmiclaude
andcommitted
fix(android): preload NDK integration for CoreCLR
Enable the io.sentry.ndk.preload metadata so that SentryNdkPreloadProvider installs sentry-native's signal handlers before .NET/CoreCLR. This ensures the correct handler chain order (.NET -> sentry-native -> debuggerd) where .NET handles managed exceptions first, and native crashes chain to sentry-native. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 39ea4d8 commit e5df035

File tree

5 files changed

+38
-12
lines changed

5 files changed

+38
-12
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
<Project>
22
<!-- Don't include parent Directory.Build.targets -->
3+
4+
<!-- Needed for SetAndroidNdkPreload (buildTransitive doesn't apply via ProjectReference) -->
5+
<Import Project="../src/Sentry/buildTransitive/Sentry.props" Condition="Exists('../src/Sentry/buildTransitive/Sentry.props')" />
6+
<Import Project="../src/Sentry/buildTransitive/Sentry.targets" Condition="Exists('../src/Sentry/buildTransitive/Sentry.targets')" />
37
</Project>

integration-test/android.Tests.ps1

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,13 @@ BeforeDiscovery {
1818
}
1919

2020
$cases = @(
21-
@{ configuration = 'Release' }
22-
@{ configuration = 'Debug' }
21+
# TODO: uncomment mono tests (#4676)
22+
#@{ configuration = 'Release'; runtime = 'mono' }
23+
@{ configuration = 'Release'; runtime = 'coreclr' }
24+
#@{ configuration = 'Debug'; runtime = 'mono' }
25+
@{ configuration = 'Debug'; runtime = 'coreclr' }
2326
)
24-
Describe 'MAUI app (<dotnet_version>, <configuration>)' -ForEach $cases -Skip:(-not $script:emulator) {
27+
Describe 'MAUI app (<dotnet_version>, <configuration>, <runtime>)' -ForEach $cases -Skip:(-not $script:emulator) {
2528
BeforeAll {
2629
$tfm = "$dotnet_version-android$(GetAndroidTpv $dotnet_version)"
2730

@@ -38,10 +41,12 @@ Describe 'MAUI app (<dotnet_version>, <configuration>)' -ForEach $cases -Skip:(-
3841
$rid = "android-$arch"
3942

4043
Write-Host "::group::Build Sentry.Maui.Device.IntegrationTestApp.csproj"
44+
$useMonoRuntime = if ($runtime -eq 'mono') { 'true' } else { 'false' }
4145
dotnet build Sentry.Maui.Device.IntegrationTestApp.csproj `
4246
--configuration $configuration `
4347
--framework $tfm `
44-
--runtime $rid
48+
--runtime $rid `
49+
-p:UseMonoRuntime=$useMonoRuntime
4550
| ForEach-Object { Write-Host $_ }
4651
Write-Host '::endgroup::'
4752
$LASTEXITCODE | Should -Be 0
@@ -177,13 +182,8 @@ Describe 'MAUI app (<dotnet_version>, <configuration>)' -ForEach $cases -Skip:(-
177182
Dump-ServerErrors -Result $result
178183
$result.HasErrors() | Should -BeFalse
179184
$result.Events() | Should -AnyElementMatch "`"type`":`"System.NullReferenceException`""
180-
# TODO: fix redundant SIGSEGV in Release (#3954)
181-
if ($configuration -eq "Release") {
182-
{ $result.Events() | Should -Not -AnyElementMatch "`"type`":`"SIGSEGV`"" } | Should -Throw
183-
} else {
184-
$result.Events() | Should -Not -AnyElementMatch "`"type`":`"SIGSEGV`""
185-
$result.Events() | Should -HaveCount 1
186-
}
185+
$result.Events() | Should -Not -AnyElementMatch "`"type`":`"SIGSEGV`""
186+
$result.Events() | Should -HaveCount 1
187187
}
188188

189189
It 'Delivers battery breadcrumbs in main thread (<configuration>)' {

src/Sentry/Platforms/Android/SentrySdk.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ namespace Sentry;
2222
public static partial class SentrySdk
2323
{
2424
private static AndroidContext AppContext { get; set; } = Application.Context;
25+
private static bool IsMonoRuntime => Type.GetType("Mono.RuntimeStructs") != null;
2526

2627
private static void InitSentryAndroidSdk(SentryOptions options)
2728
{
@@ -64,7 +65,11 @@ private static void InitSentryAndroidSdk(SentryOptions options)
6465
o.ServerName = options.ServerName;
6566
o.SessionTrackingIntervalMillis = (long)options.AutoSessionTrackingInterval.TotalMilliseconds;
6667
o.ShutdownTimeoutMillis = (long)options.ShutdownTimeout.TotalMilliseconds;
67-
o.SetNativeHandlerStrategy(JavaSdk.Android.Core.NdkHandlerStrategy.SentryHandlerStrategyDefault);
68+
if (!IsMonoRuntime)
69+
{
70+
// TODO: exclude ChainAtStart when running on CoreCLR (#4676)
71+
o.SetNativeHandlerStrategy(JavaSdk.Android.Core.NdkHandlerStrategy.SentryHandlerStrategyDefault);
72+
}
6873

6974
if (options.CacheDirectoryPath is { } cacheDirectoryPath)
7075
{

src/Sentry/buildTransitive/Sentry.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@
55
<_SentryTargetFrameworkVersion>$([MSBuild]::GetTargetFrameworkVersion($(TargetFramework)))</_SentryTargetFrameworkVersion>
66
<_SentryIsNet8OrGreater>$([MSBuild]::VersionGreaterThanOrEquals($(_SentryTargetFrameworkVersion), 8.0))</_SentryIsNet8OrGreater>
77
<_SentryIsNet9OrGreater>$([MSBuild]::VersionGreaterThanOrEquals($(_SentryTargetFrameworkVersion), 9.0))</_SentryIsNet9OrGreater>
8+
<_SentryIsNet10OrGreater>$([MSBuild]::VersionGreaterThanOrEquals($(_SentryTargetFrameworkVersion), 10.0))</_SentryIsNet10OrGreater>
89
</PropertyGroup>
910
</Project>

src/Sentry/buildTransitive/Sentry.targets

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,22 @@
281281
</ItemGroup>
282282
</Target>
283283

284+
<!-- Preload NDK to ensure sentry-native's signal handlers are installed before .NET runtime's.
285+
Disabled on Mono until: https://github.com/dotnet/runtime/pull/125835 -->
286+
<Target Name="SetAndroidNdkPreload"
287+
BeforeTargets="GetAssemblyAttributes"
288+
Condition="'$(AndroidApplication)' == 'True'
289+
and $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'
290+
and '$(_SentryIsNet10OrGreater)' == 'true'
291+
and '$(UseMonoRuntime)' != 'true'">
292+
<ItemGroup>
293+
<AssemblyAttribute Include="Android.App.MetaData">
294+
<_Parameter1>io.sentry.ndk.preload</_Parameter1>
295+
<Value>true</Value>
296+
</AssemblyAttribute>
297+
</ItemGroup>
298+
</Target>
299+
284300
<!-- Upload Android ProGuard mapping file to Sentry after the build. -->
285301
<Target Name="UploadAndroidProGuardMappingFileToSentry" AfterTargets="Build" DependsOnTargets="PrepareSentryCLI"
286302
Condition="'$(SentryCLI)' != '' and '$(SentryUploadAndroidProGuardMapping)' == 'true' And '$(AndroidProguardMappingFile)' != ''">

0 commit comments

Comments
 (0)