diff --git a/CHANGELOG.md b/CHANGELOG.md index 435f04582..7d2a423dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Fixes +- Fixed an issue where screenshot capture triggered on a burst job would crash the game. The SDK can now also capture screenshots on events that occur outside of the main thread ([#2392](https://github.com/getsentry/sentry-unity/pull/2392)) - Structured logs now have the `origin` and `sdk` attributes correctly set ([#2390](https://github.com/getsentry/sentry-unity/pull/2390)) - Resolved possible startup crashes on Android VR platforms like the Oculus Quest. The SDK no longer natively subscribes to interaction hooks for automatic tracing and breadcrumb creation. ([#2393](https://github.com/getsentry/sentry-unity/pull/2393)) diff --git a/samples/unity-of-bugs/Assets/Scenes/3_AdditionalSamples.unity b/samples/unity-of-bugs/Assets/Scenes/3_AdditionalSamples.unity index df0951bed..85086bcb6 100644 --- a/samples/unity-of-bugs/Assets/Scenes/3_AdditionalSamples.unity +++ b/samples/unity-of-bugs/Assets/Scenes/3_AdditionalSamples.unity @@ -13,7 +13,7 @@ OcclusionCullingSettings: --- !u!104 &2 RenderSettings: m_ObjectHideFlags: 0 - serializedVersion: 10 + serializedVersion: 9 m_Fog: 0 m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} m_FogMode: 3 @@ -42,8 +42,8 @@ RenderSettings: --- !u!157 &3 LightmapSettings: m_ObjectHideFlags: 0 - serializedVersion: 13 - m_BakeOnSceneLoad: 0 + serializedVersion: 12 + m_GIWorkflowMode: 1 m_GISettings: serializedVersion: 2 m_BounceScale: 1 @@ -66,6 +66,9 @@ LightmapSettings: m_LightmapParameters: {fileID: 0} m_LightmapsBakeMode: 1 m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 m_ReflectionCompression: 2 m_MixedBakeMode: 2 m_BakeBackend: 0 @@ -100,7 +103,7 @@ NavMeshSettings: serializedVersion: 2 m_ObjectHideFlags: 0 m_BuildSettings: - serializedVersion: 3 + serializedVersion: 2 agentTypeID: 0 agentRadius: 0.5 agentHeight: 2 @@ -113,7 +116,7 @@ NavMeshSettings: cellSize: 0.16666667 manualTileSize: 0 tileSize: 256 - buildHeightMesh: 0 + accuratePlacement: 0 maxJobWorkers: 0 preserveTilesOutsideBounds: 0 debug: @@ -153,7 +156,9 @@ RectTransform: - {fileID: 1326160953} - {fileID: 1983589452} - {fileID: 978406552} + - {fileID: 2066465601} m_Father: {fileID: 1665572489} + m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 1, y: 1} @@ -229,17 +234,9 @@ Camera: m_projectionMatrixMode: 1 m_GateFitMode: 2 m_FOVAxisMode: 0 - m_Iso: 200 - m_ShutterSpeed: 0.005 - m_Aperture: 16 - m_FocusDistance: 10 - m_FocalLength: 50 - m_BladeCount: 5 - m_Curvature: {x: 2, y: 11} - m_BarrelClipping: 0.25 - m_Anamorphism: 0 m_SensorSize: {x: 36, y: 24} m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 m_NormalizedViewPortRect: serializedVersion: 2 x: 0 @@ -273,13 +270,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 519420028} - serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: -10} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} + m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &582054325 GameObject: @@ -321,13 +318,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 582054325} - serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} + m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &582054329 MonoBehaviour: @@ -370,6 +367,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 5216638424148094703} + m_RootOrder: 5 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -407,6 +405,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 978406552} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -488,6 +487,7 @@ RectTransform: m_Children: - {fileID: 834374186} m_Father: {fileID: 253040315} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -619,6 +619,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 802360430} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -698,6 +699,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1983589452} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -779,6 +781,7 @@ RectTransform: m_Children: - {fileID: 765642146} m_Father: {fileID: 253040315} + m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -912,6 +915,7 @@ RectTransform: m_Children: - {fileID: 1857152829} m_Father: {fileID: 253040315} + m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -1012,6 +1016,86 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1326160952} m_CullTransparentMesh: 0 +--- !u!1 &1583546086 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1583546087} + - component: {fileID: 1583546089} + - component: {fileID: 1583546088} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1583546087 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1583546086} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 2066465601} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1583546088 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1583546086} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 1 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: LogError in Burst Job +--- !u!222 &1583546089 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1583546086} + m_CullTransparentMesh: 0 --- !u!1 &1665572488 GameObject: m_ObjectHideFlags: 0 @@ -1047,6 +1131,7 @@ RectTransform: - {fileID: 253040315} - {fileID: 5216638424148094703} m_Father: {fileID: 0} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -1112,7 +1197,6 @@ Canvas: m_SortingBucketNormalizedSize: 0 m_VertexColorAlwaysGammaSpace: 0 m_AdditionalShaderChannelsFlag: 0 - m_UpdateRectTransformForStandalone: 0 m_SortingLayerID: 0 m_SortingOrder: 0 m_TargetDisplay: 0 @@ -1147,6 +1231,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1326160953} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -1228,6 +1313,7 @@ RectTransform: m_Children: - {fileID: 908640125} m_Father: {fileID: 253040315} + m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -1328,6 +1414,140 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1983589451} m_CullTransparentMesh: 0 +--- !u!1 &2066465600 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2066465601} + - component: {fileID: 2066465604} + - component: {fileID: 2066465603} + - component: {fileID: 2066465602} + m_Layer: 5 + m_Name: Burst Job + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2066465601 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2066465600} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1583546087} + m_Father: {fileID: 253040315} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 200, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &2066465602 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2066465600} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 2066465603} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 253040317} + m_TargetAssemblyTypeName: AdditionalSampleButtons, Assembly-CSharp + m_MethodName: StartBuggyBurstJob + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 1 +--- !u!114 &2066465603 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2066465600} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &2066465604 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2066465600} + m_CullTransparentMesh: 0 --- !u!1 &5216638424148094696 GameObject: m_ObjectHideFlags: 0 @@ -1403,6 +1623,7 @@ RectTransform: - {fileID: 5216638425317031111} - {fileID: 735359052} m_Father: {fileID: 1665572489} + m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0} m_AnchorMax: {x: 0.5, y: 0} @@ -1482,6 +1703,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 5216638425317031111} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -1543,6 +1765,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 5216638425882040144} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -1614,6 +1837,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 5216638424148094703} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -1773,6 +1997,7 @@ RectTransform: m_Children: - {fileID: 5216638424536828319} m_Father: {fileID: 5216638424148094703} + m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -1887,6 +2112,7 @@ RectTransform: m_Children: - {fileID: 5216638426142319615} m_Father: {fileID: 5216638424148094703} + m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -1926,6 +2152,7 @@ RectTransform: m_Children: - {fileID: 5216638425035397373} m_Father: {fileID: 5216638424148094703} + m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -2074,6 +2301,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 5216638424148094703} + m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -2153,6 +2381,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 5216638425805414493} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -2224,6 +2453,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 7152012675849339084} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -2253,6 +2483,7 @@ RectTransform: - {fileID: 7152012675148913643} - {fileID: 7152012676968016302} m_Father: {fileID: 1665572489} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 1} m_AnchorMax: {x: 1, y: 1} @@ -2330,6 +2561,7 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 7152012675849339084} + m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -2354,10 +2586,3 @@ GameObject: m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!1660057539 &9223372036854775807 -SceneRoots: - m_ObjectHideFlags: 0 - m_Roots: - - {fileID: 519420032} - - {fileID: 582054328} - - {fileID: 1665572489} diff --git a/samples/unity-of-bugs/Assets/Scripts/AdditionalSampleButtons.cs b/samples/unity-of-bugs/Assets/Scripts/AdditionalSampleButtons.cs index cfde60315..0bfac1503 100644 --- a/samples/unity-of-bugs/Assets/Scripts/AdditionalSampleButtons.cs +++ b/samples/unity-of-bugs/Assets/Scripts/AdditionalSampleButtons.cs @@ -1,6 +1,9 @@ -using System.Threading; +using System; +using System.Threading; using Sentry; using Sentry.Unity; +using Unity.Burst; +using Unity.Jobs; using UnityEngine; public class AdditionalSampleButtons : MonoBehaviour @@ -50,4 +53,22 @@ public void ApplicationNotResponding() } public void Assert() => UnityEngine.Assertions.Assert.IsTrue(false); + + + [BurstCompile] + private struct BuggyBurstJob : IJob + { + public void Execute() + { + Debug.LogError("Bursting with bugs! 💥"); + } + } + + public void StartBuggyBurstJob() + { + Debug.Log("Starting Burst job filled with bugs! 💥"); + var job = new BuggyBurstJob(); + var handle = job.Schedule(); + handle.Complete(); + } } diff --git a/samples/unity-of-bugs/Packages/manifest.json b/samples/unity-of-bugs/Packages/manifest.json index b591aa1ff..727dc350f 100644 --- a/samples/unity-of-bugs/Packages/manifest.json +++ b/samples/unity-of-bugs/Packages/manifest.json @@ -1,6 +1,7 @@ { "dependencies": { - "com.unity.collab-proxy": "2.9.3", + "com.unity.burst": "1.8.25", + "com.unity.collab-proxy": "2.10.1", "com.unity.feature.development": "1.0.1", "com.unity.ide.rider": "3.0.38", "com.unity.ide.visualstudio": "2.0.23", @@ -10,7 +11,7 @@ "com.unity.textmeshpro": "3.0.9", "com.unity.timeline": "1.6.5", "com.unity.ugui": "1.0.0", - "com.unity.visualscripting": "1.9.8", + "com.unity.visualscripting": "1.9.9", "io.sentry.unity.dev": "file:../../../package-dev", "com.unity.modules.ai": "1.0.0", "com.unity.modules.androidjni": "1.0.0", diff --git a/samples/unity-of-bugs/Packages/packages-lock.json b/samples/unity-of-bugs/Packages/packages-lock.json index d2fca6059..fbe6f3c53 100644 --- a/samples/unity-of-bugs/Packages/packages-lock.json +++ b/samples/unity-of-bugs/Packages/packages-lock.json @@ -1,7 +1,17 @@ { "dependencies": { + "com.unity.burst": { + "version": "1.8.25", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.mathematics": "1.2.1", + "com.unity.modules.jsonserialize": "1.0.0" + }, + "url": "https://packages.unity.com" + }, "com.unity.collab-proxy": { - "version": "2.9.3", + "version": "2.10.1", "depth": 0, "source": "registry", "dependencies": {}, @@ -27,10 +37,10 @@ "source": "builtin", "dependencies": { "com.unity.ide.visualstudio": "2.0.22", - "com.unity.ide.rider": "3.0.31", + "com.unity.ide.rider": "3.0.38", "com.unity.ide.vscode": "1.2.5", "com.unity.editorcoroutines": "1.0.0", - "com.unity.performance.profile-analyzer": "1.2.2", + "com.unity.performance.profile-analyzer": "1.2.3", "com.unity.test-framework": "1.1.33", "com.unity.testtools.codecoverage": "1.2.6" } @@ -60,6 +70,13 @@ "dependencies": {}, "url": "https://packages.unity.com" }, + "com.unity.mathematics": { + "version": "1.2.6", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, "com.unity.mobile.android-logcat": { "version": "1.4.6", "depth": 0, @@ -68,7 +85,7 @@ "url": "https://packages.unity.com" }, "com.unity.performance.profile-analyzer": { - "version": "1.2.2", + "version": "1.2.3", "depth": 1, "source": "registry", "dependencies": {}, @@ -133,7 +150,7 @@ } }, "com.unity.visualscripting": { - "version": "1.9.8", + "version": "1.9.9", "depth": 0, "source": "registry", "dependencies": { diff --git a/samples/unity-of-bugs/ProjectSettings/ProjectVersion.txt b/samples/unity-of-bugs/ProjectSettings/ProjectVersion.txt index 1a62a673a..d8cedffba 100644 --- a/samples/unity-of-bugs/ProjectSettings/ProjectVersion.txt +++ b/samples/unity-of-bugs/ProjectSettings/ProjectVersion.txt @@ -1,2 +1,2 @@ -m_EditorVersion: 2021.3.45f2 -m_EditorVersionWithRevision: 2021.3.45f2 (88f88f591b2e) +m_EditorVersion: 2021.3.58f1 +m_EditorVersionWithRevision: 2021.3.58f1 (2c36cafeeccf) diff --git a/scripts/ci-env.ps1 b/scripts/ci-env.ps1 index f80b7e23d..60255bf79 100644 --- a/scripts/ci-env.ps1 +++ b/scripts/ci-env.ps1 @@ -5,7 +5,7 @@ param ( switch ($name) { "unity2021.3" { - return "2021.3.45f2" + return "2021.3.58f1" } "unity2022.3" { return "2022.3.62f3" diff --git a/src/Sentry.Unity/ScreenshotEventProcessor.cs b/src/Sentry.Unity/ScreenshotEventProcessor.cs index 57a22093a..0e1150c55 100644 --- a/src/Sentry.Unity/ScreenshotEventProcessor.cs +++ b/src/Sentry.Unity/ScreenshotEventProcessor.cs @@ -26,7 +26,8 @@ public SentryEvent Process(SentryEvent @event) // Only ever capture one screenshot per frame if (Interlocked.CompareExchange(ref _isCapturingScreenshot, 1, 0) == 0) { - _sentryMonoBehaviour.StartCoroutine(CaptureScreenshotCoroutine(@event.EventId)); + _options.LogDebug("Starting coroutine to capture a screenshot."); + _sentryMonoBehaviour.QueueCoroutine(CaptureScreenshotCoroutine(@event.EventId)); } return @event; diff --git a/src/Sentry.Unity/SentryMonoBehaviour.cs b/src/Sentry.Unity/SentryMonoBehaviour.cs index 4b1ff5f88..cb6a3d611 100644 --- a/src/Sentry.Unity/SentryMonoBehaviour.cs +++ b/src/Sentry.Unity/SentryMonoBehaviour.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using System.Collections.Concurrent; using Sentry.Unity.Integrations; using UnityEngine; @@ -9,6 +10,7 @@ internal interface ISentryMonoBehaviour { event Action? ApplicationResuming; public Coroutine StartCoroutine(IEnumerator routine); + public void QueueCoroutine(IEnumerator routine); } /// @@ -51,6 +53,30 @@ public void StartAwakeSpan(MonoBehaviour monoBehaviour) => /// public partial class SentryMonoBehaviour { + // Unbounded queue - used by the ScreenshotEventProcessor where capture is already limited by Interlocked to 1/frame + private readonly ConcurrentQueue _coroutineQueue = new(); + + public void QueueCoroutine(IEnumerator routine) + { + if (MainThreadData.IsMainThread()) + { + StartCoroutine(routine); + } + else + { + // On background thread (e.g., Burst job) - queue for next Update() + _coroutineQueue.Enqueue(routine); + } + } + + private void Update() + { + while (_coroutineQueue.TryDequeue(out var coroutine)) + { + StartCoroutine(coroutine); + } + } + /// /// Hook to receive an event when the application gains focus. /// diff --git a/test/Scripts.Integration.Test/Scripts/SmokeTester.cs b/test/Scripts.Integration.Test/Scripts/SmokeTester.cs index 8e7f76a16..ead8d2d87 100644 --- a/test/Scripts.Integration.Test/Scripts/SmokeTester.cs +++ b/test/Scripts.Integration.Test/Scripts/SmokeTester.cs @@ -214,7 +214,33 @@ private IEnumerator SmokeTestCoroutine() t.ExpectMessage(currentMessage, "'filename':'screenshot.jpg','attachment_type':'event.attachment'"); t.ExpectMessageNot(currentMessage, "'length':0"); - + +#if !UNITY_WEBGL + // Test screenshot capture from background thread + var backgroundThreadGuid = Guid.NewGuid().ToString(); + var backgroundThreadTask = Task.Run(() => + { + Debug.Log($"Background thread: Capturing exception with GUID={backgroundThreadGuid}"); + Debug.LogError($"BackgroundThreadException(GUID)={backgroundThreadGuid}"); + }); + backgroundThreadTask.Wait(); + + // Wait for screenshot capture to complete + yield return null; + // The capture coroutine gets queued up to be started in the next Update(), wait for that + yield return null; + + currentMessage++; // The background thread exception event + + t.ExpectMessage(currentMessage, "'type':'event'"); + t.ExpectMessage(currentMessage, $"BackgroundThreadException(GUID)={backgroundThreadGuid}"); + t.ExpectMessageNot(currentMessage, "'length':0"); + + currentMessage++; // The screenshot envelope from background thread + + t.ExpectMessage(currentMessage, "'filename':'screenshot.jpg','attachment_type':'event.attachment'"); + t.ExpectMessageNot(currentMessage, "'length':0"); +#endif Debug.Log("Finished checking messages."); t.Pass(); diff --git a/test/Sentry.Unity.Tests/SentryMonoBehaviourTests.cs b/test/Sentry.Unity.Tests/SentryMonoBehaviourTests.cs index 8b7e6ed45..586b1dea1 100644 --- a/test/Sentry.Unity.Tests/SentryMonoBehaviourTests.cs +++ b/test/Sentry.Unity.Tests/SentryMonoBehaviourTests.cs @@ -1,4 +1,6 @@ using System.Collections; +using System.Threading; +using System.Threading.Tasks; using NUnit.Framework; using Sentry.Unity.Tests.Stubs; using UnityEngine; @@ -81,4 +83,49 @@ public void UpdatePauseStatus_ResumedTwice_ApplicationResumingInvokedOnlyOnce() Assert.AreEqual(1, counter); } + [Test] + public void QueueCoroutine_CalledOnMainThread_StartsCoroutineImmediately() + { + var sut = _fixture.GetSut(); + var coroutineExecuted = false; + + IEnumerator TestCoroutine() + { + coroutineExecuted = true; + yield return null; + } + + sut.QueueCoroutine(TestCoroutine()); + + Assert.IsTrue(coroutineExecuted); + } + + [UnityTest] + public IEnumerator QueueCoroutine_QueuedOnBackgroundThread_StartsInUpdate() + { + var sut = _fixture.GetSut(); + var coroutineExecuted = false; + + IEnumerator TestCoroutine() + { + coroutineExecuted = true; + yield return null; + } + + var thread = new Thread(() => + { + sut.QueueCoroutine(TestCoroutine()); + }); + + thread.Start(); + thread.Join(); + + // Coroutine should not have started yet + Assert.IsFalse(coroutineExecuted); + + // Wait for the coroutine to execute - trigger `Update` + yield return null; + + Assert.IsTrue(coroutineExecuted); + } } diff --git a/test/Sentry.Unity.Tests/Stubs/SentryTestMonoBehaviour.cs b/test/Sentry.Unity.Tests/Stubs/SentryTestMonoBehaviour.cs index 12ffb5add..f911d21b9 100644 --- a/test/Sentry.Unity.Tests/Stubs/SentryTestMonoBehaviour.cs +++ b/test/Sentry.Unity.Tests/Stubs/SentryTestMonoBehaviour.cs @@ -16,4 +16,10 @@ internal class TestSentryMonoBehaviour : MonoBehaviour, ISentryMonoBehaviour StartCoroutineCalled = true; return base.StartCoroutine(routine); } + + public void QueueCoroutine(IEnumerator routine) + { + // For tests, assume we're on the main thread and start immediately + StartCoroutine(routine); + } }