Skip to content

Commit b3c12ec

Browse files
Workaround thread safety issues accessing Android device data
1 parent 9bea4f5 commit b3c12ec

File tree

5 files changed

+28
-8
lines changed

5 files changed

+28
-8
lines changed

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<VersionPrefix>5.0.0-alpha.1</VersionPrefix>
5-
<LangVersion>12</LangVersion>
5+
<LangVersion>13</LangVersion>
66
<AccelerateBuildsInVisualStudio>true</AccelerateBuildsInVisualStudio>
77
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
88
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory).assets\Sentry.snk</AssemblyOriginatorKeyFile>

src/Sentry.Maui/Internal/MauiDeviceData.cs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,28 @@ namespace Sentry.Maui.Internal;
66

77
internal static class MauiDeviceData
88
{
9-
public static void ApplyMauiDeviceData(this Device device, IDiagnosticLogger? logger)
9+
#if NET9_0_OR_GREATER && ANDROID
10+
private static readonly Lock JniLock = new();
11+
#elif ANDROID
12+
private static readonly object JniLock = new();
13+
#endif
14+
15+
public static void ApplyMauiDeviceData(this Device device, IDiagnosticLogger? logger,
16+
INetworkStatusListener? networkStatusListener)
17+
{
18+
#if ANDROID
19+
// Accessing device information on Android doesn't have to happen on the UI thread, but it's not threadsafe.
20+
// See: https://github.com/getsentry/sentry-dotnet/issues/3627
21+
lock (JniLock)
22+
{
23+
ApplyMauiDeviceDataInternal(device, logger, networkStatusListener);
24+
}
25+
#else
26+
ApplyMauiDeviceDataInternal(device, logger, networkStatusListener);
27+
#endif
28+
}
29+
30+
private static void ApplyMauiDeviceDataInternal(Device device, IDiagnosticLogger? logger, INetworkStatusListener? networkStatusListener)
1031
{
1132
try
1233
{
@@ -54,10 +75,9 @@ public static void ApplyMauiDeviceData(this Device device, IDiagnosticLogger? lo
5475
logger?.LogDebug("No permission to read battery state from the device.");
5576
}
5677

57-
// https://docs.microsoft.com/dotnet/maui/platform-integration/communication/networking#using-connectivity
5878
try
5979
{
60-
device.IsOnline ??= Connectivity.NetworkAccess == NetworkAccess.Internet;
80+
device.IsOnline ??= networkStatusListener?.Online;
6181
}
6282
catch (PermissionException)
6383
{

src/Sentry.Maui/Internal/SentryMauiEventProcessor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public SentryEvent Process(SentryEvent @event)
1717
{
1818
@event.Sdk.Name = Constants.SdkName;
1919
@event.Sdk.Version = Constants.SdkVersion;
20-
@event.Contexts.Device.ApplyMauiDeviceData(_options.DiagnosticLogger);
20+
@event.Contexts.Device.ApplyMauiDeviceData(_options.DiagnosticLogger, _options.NetworkStatusListener);
2121
@event.Contexts.OperatingSystem.ApplyMauiOsData(_options.DiagnosticLogger);
2222
@event.Contexts.App.InForeground = InForeground;
2323

src/Sentry/Internal/Http/CachingTransport.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ internal class CachingTransport : ITransport, IDisposable
4141
// and write from/to the cache directory.
4242
// Lock usage is minimized by moving files that are being processed to a special directory
4343
// where collisions are not expected.
44-
private readonly Lock _cacheDirectoryLock = new();
44+
private readonly SentryLock _cacheDirectoryLock = new();
4545

4646
private readonly CancellationTokenSource _workerCts = new();
4747
private Task _worker = null!;
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
namespace Sentry.Internal;
22

3-
internal class Lock : IDisposable
3+
internal class SentryLock : IDisposable
44
{
55
private readonly Signal _signal;
66

7-
public Lock() => _signal = new Signal(true);
7+
public SentryLock() => _signal = new Signal(true);
88

99
public async Task<IDisposable> AcquireAsync(CancellationToken cancellationToken = default)
1010
{

0 commit comments

Comments
 (0)