Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
Workaround thread safety issues accessing Android device data
  • Loading branch information
jamescrosswell committed Nov 28, 2024
commit b3c12ec19dccd08ca15e7dea35cbf8f0c065075a
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<VersionPrefix>5.0.0-alpha.1</VersionPrefix>
<LangVersion>12</LangVersion>
<LangVersion>13</LangVersion>
<AccelerateBuildsInVisualStudio>true</AccelerateBuildsInVisualStudio>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory).assets\Sentry.snk</AssemblyOriginatorKeyFile>
Expand Down
26 changes: 23 additions & 3 deletions src/Sentry.Maui/Internal/MauiDeviceData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,28 @@ namespace Sentry.Maui.Internal;

internal static class MauiDeviceData
{
public static void ApplyMauiDeviceData(this Device device, IDiagnosticLogger? logger)
#if NET9_0_OR_GREATER && ANDROID
private static readonly Lock JniLock = new();
#elif ANDROID
private static readonly object JniLock = new();
#endif

public static void ApplyMauiDeviceData(this Device device, IDiagnosticLogger? logger,
INetworkStatusListener? networkStatusListener)
{
#if ANDROID
// Accessing device information on Android doesn't have to happen on the UI thread, but it's not threadsafe.
// See: https://github.com/getsentry/sentry-dotnet/issues/3627
lock (JniLock)
{
ApplyMauiDeviceDataInternal(device, logger, networkStatusListener);
}
#else
ApplyMauiDeviceDataInternal(device, logger, networkStatusListener);
#endif
}

private static void ApplyMauiDeviceDataInternal(Device device, IDiagnosticLogger? logger, INetworkStatusListener? networkStatusListener)
{
try
{
Expand Down Expand Up @@ -54,10 +75,9 @@ public static void ApplyMauiDeviceData(this Device device, IDiagnosticLogger? lo
logger?.LogDebug("No permission to read battery state from the device.");
}

// https://docs.microsoft.com/dotnet/maui/platform-integration/communication/networking#using-connectivity
try
{
device.IsOnline ??= Connectivity.NetworkAccess == NetworkAccess.Internet;
device.IsOnline ??= networkStatusListener?.Online;
}
catch (PermissionException)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Sentry.Maui/Internal/SentryMauiEventProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public SentryEvent Process(SentryEvent @event)
{
@event.Sdk.Name = Constants.SdkName;
@event.Sdk.Version = Constants.SdkVersion;
@event.Contexts.Device.ApplyMauiDeviceData(_options.DiagnosticLogger);
@event.Contexts.Device.ApplyMauiDeviceData(_options.DiagnosticLogger, _options.NetworkStatusListener);
@event.Contexts.OperatingSystem.ApplyMauiOsData(_options.DiagnosticLogger);
@event.Contexts.App.InForeground = InForeground;

Expand Down
2 changes: 1 addition & 1 deletion src/Sentry/Internal/Http/CachingTransport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ internal class CachingTransport : ITransport, IDisposable
// and write from/to the cache directory.
// Lock usage is minimized by moving files that are being processed to a special directory
// where collisions are not expected.
private readonly Lock _cacheDirectoryLock = new();
private readonly SentryLock _cacheDirectoryLock = new();

private readonly CancellationTokenSource _workerCts = new();
private Task _worker = null!;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
namespace Sentry.Internal;

internal class Lock : IDisposable
internal class SentryLock : IDisposable
{
private readonly Signal _signal;

public Lock() => _signal = new Signal(true);
public SentryLock() => _signal = new Signal(true);

public async Task<IDisposable> AcquireAsync(CancellationToken cancellationToken = default)
{
Expand Down
Loading