getsentry / sentry-xamarin

Sentry for Xamarin Native and Xamarin.Forms
https://docs.sentry.io/platforms/dotnet/guides/xamarin/
44 stars 11 forks source link

Sentry is trying to get a Screenshot when not on the UI Thread #155

Open munkii opened 1 week ago

munkii commented 1 week ago

Xamarin Forms iOS

2.1.0

Steps to Reproduce

  1. Ensure that options.AttachScreenshots is set to True at Init time
  2. Throw an Exception on a Background thread and ensure the call to Log in Sentry is done on the Background Thread
  3. Sentry will try and Capture via Xamarin Essentials.
  4. Xmarin Essentials Screenshot functionality must be called on the UIThread

Expected Result

The exception will get logged in Sentry

Actual Result

We are in the process of moving from AppCenter so for now we have AppCenter AND Sentry running at the same time. We only knew this was happening because we were seeing SIGTRAP crashes in AppCenter.

The initial discussion took place on Discord, https://discordapp.com/channels/621778831602221064/1303772061050601604

After uploading a dSYM file to AppCenter we see the following call stack.

Exception Type: SIGTRAP Exception Codes: #0 at 0x1b54b9edc Crashed Thread: 32

Thread 32 Crashed: 0 FrontBoardServices 0x00000001b54b9edc -[FBSMainRunLoopSerialQueue assertBarrierOnQueue] + 140 1 FrontBoardServices 0x00000001b54c003c -[FBSScene attachLayer:] + 36 2 UIKitCore 0x000000019ecaa8ac -[_UIFBSSceneSubstrate attachContext:] + 128 3 UIKitCore 0x000000019ecaa5fc __UIContextBinderAttachContext + 236 4 UIKitCore 0x000000019ebe37d8 -[_UIContextBinder attachBindable:] + 316 5 UIKitCore 0x000000019ebe2700 -[UIWindowScene _windowUpdatedVisibility:] + 356 6 UIKitCore 0x000000019ebe15dc -[UIWindow _updateLayerOrderingAndSetLayerHidden:actionBlock:] + 188 7 UIKitCore 0x000000019ebe12f0 -[UIWindow _setHidden:forced:] + 252 8 UIKitCore 0x000000019f9e561c ___coverCanvases_block_invoke + 152 9 UIKitCore 0x000000019f9e52ac _enumScenes + 204 10 UIKitCore 0x000000019f9e2f78 _performAfterContextCommitUnderCoverAllowDefer + 260 11 UIKitCore 0x000000019f9e1ca8 _UIRenderViewImageAfterCommit + 672 12 UIKitCore 0x000000019fdced1c -[UIView drawViewHierarchyInRect:afterScreenUpdates:] + 420 13 OurApp 0x0000000105945bc8 wrapper_managed_to_native_ObjCRuntime_Messaging_objc_msgSend_intptr_intptr_CoreGraphics_CGRect_bool_0 + 180 14 OurApp 0x000000010587d85c UIKit_UIView_DrawViewHierarchy_CoreGraphics_CGRect_bool (UIView.g.cs:786) 15 OurApp 0x000000010586d41c UIKit_UIScreen_Capture (UIScreen.cs:37) 16 OurApp 0x000000010634f60c Xamarin_Essentials_Screenshot_PlatformCaptureAsync (D:\a_work\1\s\Xamarin.Essentials\Screenshot\Screenshot.ios.tvos.cs:14) 17 OurApp 0x000000010634f598 Xamarin_Essentials_Screenshot_CaptureAsync (D:\a_work\1\s\Xamarin.Essentials\Screenshot\Screenshot.shared.cs:16) 18 OurApp 0x00000001083ca780 Sentry_Internals_Device_Screenshot_ScreenshotAttachmentContent_GetStream (D:\a\sentry-xamarin\sentry-xamarin\Src\Sentry.Xamarin\Internals\Device\Screenshot\ScreenshotAttachmentContent.cs:11) 19 OurApp 0x00000001068465b0 Sentry_Protocol_Envelopes_Envelope_FromEvent_Sentry_SentryEvent_Sentry_Extensibility_IDiagnosticLogger_System_Collections_Generic_IReadOnlyCollection_1_Sentry_SentryAttachment_Sentry_SessionUpdate (:1) 20 OurApp 0x00000001067fc7e4 Sentry_SentryClient_DoSendEvent_Sentry_SentryEvent_Sentry_SentryHint_Sentry_Scope (:1) 21 OurApp 0x00000001067fb040 Sentry_SentryClient_CaptureEvent_Sentry_SentryEvent_Sentry_Scope_Sentry_SentryHint (:1) 22 OurApp 0x0000000106862aac Sentry_Internal_Hub_CaptureEvent_Sentry_SentryEvent_Sentry_Scope_Sentry_SentryHint (:1) 23 OurApp 0x00000001067fd308 Sentry_SentryClientExtensions_CaptureException_Sentry_ISentryClient_System_Exception (:1) 24 OurApp 0x0000000106814e5c Sentry_SentrySdk_CaptureException_System_Exception (:1)

Now I appreciate that Xamarin Forms is out of support and that probably means yo are not going to fix this but we feel like it needs raising.

Next week we will try and get a small repro project together

bitsandfoxes commented 1 week ago

Thanks for raising this! @lucas-zimerman what about we wrap this in

MainThread.BeginInvokeOnMainThread(() =>
{
    var screenStream = CaptureAsync().ConfigureAwait(false).GetAwaiter().GetResult();
});

Or if that does not work we could prevent this by checking MainThread.IsMainThread?