sentry-unity icon indicating copy to clipboard operation
sentry-unity copied to clipboard

`IsMainThread` check fails in burst context

Open bitsandfoxes opened this issue 4 months ago • 0 comments
trafficstars

Originates from https://discord.com/channels/621778831602221064/621778831602221072/1387406424404922561

Problem

Capturing an exception aborts the game with

UnityEngine::UnityException: GetBatteryStatus can only be called from the main thread.
Constructors and field initializers will be executed from the loading thread when loading a scene.
Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.
This Exception was thrown from a job compiled with Burst, which has limited exception support. Turn off burst (Jobs -> Burst -> Enable Compilation) to inspect full exceptions & stacktraces. In this standalone build configuration burst will now abort the Application.
Sentry.Unity.UnityEventProcessor:PopulateDevice(Device)
Sentry.Unity.UnityEventProcessor:SetEventContext(IEventLike)
Sentry.Unity.UnityEventProcessor:Process(SentryEvent)
Sentry.SentryClient:DoSendEvent(SentryEvent, SentryHint, Scope)
Sentry.SentryClient:CaptureEvent(SentryEvent, Scope, SentryHint)
Sentry.Internal.Hub:CaptureEvent(SentryEvent, SentryHint, Scope)
Sentry.Internal.Hub:CaptureEvent(SentryEvent, Scope, SentryHint)
Sentry.SentryClientExtensions:CaptureMessage(ISentryClient, String, SentryLevel)
Sentry.Unity.Integrations.UnityApplicationLoggingIntegration:OnLogMessageReceived(String, String, LogType)
[./Runtime/Jobs/ScriptBindings/JobsBindings.cpp]

Proposal

We're guarding the battery-status with a check here https://github.com/getsentry/sentry-unity/blob/a27bb31ace09e934c6f194ffb8c7393dc657873d/src/Sentry.Unity/UnityEventProcessor.cs#L54-L59

but this seems to fail in a burst compiled setting.

We'll need to update the check with something like

bool IsMainThread() => !JobsUtility.IsExecutingJob && Thread.CurrentThread.ManagedThreadId == SynchronizationContext.mainThreadId;

Repro

[BurstCompile]
public struct BadCommandJob : IJob
{
    [BurstCompile]
    public void Execute()
    {
        Debug.Log($"Log from job. I can ruin your application!");
    }
}

And on the main thread call:

var job = new BadCommandJob();
job.Run();

bitsandfoxes avatar Jun 25 '25 13:06 bitsandfoxes