From b6b0b4000d897d3ff86600cd8ea0707067193377 Mon Sep 17 00:00:00 2001 From: Artem Perepelitsa Date: Sat, 16 Oct 2021 11:55:30 +0300 Subject: [PATCH 1/2] Add unobserved task exception publishing if an exception inside ExceptionResultSource is never thrown --- .../UniTask/Runtime/UniTask.Factory.cs | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTask.Factory.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTask.Factory.cs index c56cb03..2f6a6a9 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTask.Factory.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/UniTask.Factory.cs @@ -194,6 +194,7 @@ namespace Cysharp.Threading.Tasks sealed class ExceptionResultSource : IUniTaskSource { readonly ExceptionDispatchInfo exception; + bool calledGet; public ExceptionResultSource(Exception exception) { @@ -202,6 +203,11 @@ namespace Cysharp.Threading.Tasks public void GetResult(short token) { + if (!calledGet) + { + calledGet = true; + GC.SuppressFinalize(this); + } exception.Throw(); } @@ -219,11 +225,20 @@ namespace Cysharp.Threading.Tasks { continuation(state); } + + ~ExceptionResultSource() + { + if (!calledGet) + { + UniTaskScheduler.PublishUnobservedTaskException(exception.SourceException); + } + } } sealed class ExceptionResultSource : IUniTaskSource { readonly ExceptionDispatchInfo exception; + bool calledGet; public ExceptionResultSource(Exception exception) { @@ -232,12 +247,22 @@ namespace Cysharp.Threading.Tasks public T GetResult(short token) { + if (!calledGet) + { + calledGet = true; + GC.SuppressFinalize(this); + } exception.Throw(); return default; } void IUniTaskSource.GetResult(short token) { + if (!calledGet) + { + calledGet = true; + GC.SuppressFinalize(this); + } exception.Throw(); } @@ -255,6 +280,14 @@ namespace Cysharp.Threading.Tasks { continuation(state); } + + ~ExceptionResultSource() + { + if (!calledGet) + { + UniTaskScheduler.PublishUnobservedTaskException(exception.SourceException); + } + } } sealed class CanceledResultSource : IUniTaskSource From c31b78e45e4de343a05c99d1b04df624b6036e37 Mon Sep 17 00:00:00 2001 From: Artem Perepelitsa Date: Sat, 16 Oct 2021 12:18:52 +0300 Subject: [PATCH 2/2] Add a unit test to verify that an unawaited task reports exceptions --- src/UniTask/Assets/Tests/AsyncTest.cs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/UniTask/Assets/Tests/AsyncTest.cs b/src/UniTask/Assets/Tests/AsyncTest.cs index c329dbf..75eec2c 100644 --- a/src/UniTask/Assets/Tests/AsyncTest.cs +++ b/src/UniTask/Assets/Tests/AsyncTest.cs @@ -366,6 +366,28 @@ namespace Cysharp.Threading.TasksTests UniTaskScheduler.UnobservedTaskException -= action; }); + [UnityTest] + public IEnumerator ThrowExceptionUnawaited() => UniTask.ToCoroutine(async () => + { + LogAssert.Expect(LogType.Exception, "Exception: MyException"); + +#pragma warning disable 1998 + async UniTask Throw() => throw new Exception("MyException"); +#pragma warning restore 1998 + +#pragma warning disable 4014 + Throw(); +#pragma warning restore 4014 + + await UniTask.DelayFrame(3); + + GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); + + await UniTask.DelayFrame(1); + }); + async UniTask InException1() { await UniTask.Yield();