Merge pull request #323 from SolidAlloy/throw-exception-fix

Fix exceptions never being reported when UniTask is executed without await and Forget()
master
Yoshifumi Kawai 2022-03-03 06:04:55 +09:00 committed by GitHub
commit b089f74c65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 0 deletions

View File

@ -194,6 +194,7 @@ namespace Cysharp.Threading.Tasks
sealed class ExceptionResultSource : IUniTaskSource sealed class ExceptionResultSource : IUniTaskSource
{ {
readonly ExceptionDispatchInfo exception; readonly ExceptionDispatchInfo exception;
bool calledGet;
public ExceptionResultSource(Exception exception) public ExceptionResultSource(Exception exception)
{ {
@ -202,6 +203,11 @@ namespace Cysharp.Threading.Tasks
public void GetResult(short token) public void GetResult(short token)
{ {
if (!calledGet)
{
calledGet = true;
GC.SuppressFinalize(this);
}
exception.Throw(); exception.Throw();
} }
@ -219,11 +225,20 @@ namespace Cysharp.Threading.Tasks
{ {
continuation(state); continuation(state);
} }
~ExceptionResultSource()
{
if (!calledGet)
{
UniTaskScheduler.PublishUnobservedTaskException(exception.SourceException);
}
}
} }
sealed class ExceptionResultSource<T> : IUniTaskSource<T> sealed class ExceptionResultSource<T> : IUniTaskSource<T>
{ {
readonly ExceptionDispatchInfo exception; readonly ExceptionDispatchInfo exception;
bool calledGet;
public ExceptionResultSource(Exception exception) public ExceptionResultSource(Exception exception)
{ {
@ -232,12 +247,22 @@ namespace Cysharp.Threading.Tasks
public T GetResult(short token) public T GetResult(short token)
{ {
if (!calledGet)
{
calledGet = true;
GC.SuppressFinalize(this);
}
exception.Throw(); exception.Throw();
return default; return default;
} }
void IUniTaskSource.GetResult(short token) void IUniTaskSource.GetResult(short token)
{ {
if (!calledGet)
{
calledGet = true;
GC.SuppressFinalize(this);
}
exception.Throw(); exception.Throw();
} }
@ -255,6 +280,14 @@ namespace Cysharp.Threading.Tasks
{ {
continuation(state); continuation(state);
} }
~ExceptionResultSource()
{
if (!calledGet)
{
UniTaskScheduler.PublishUnobservedTaskException(exception.SourceException);
}
}
} }
sealed class CanceledResultSource : IUniTaskSource sealed class CanceledResultSource : IUniTaskSource

View File

@ -366,6 +366,28 @@ namespace Cysharp.Threading.TasksTests
UniTaskScheduler.UnobservedTaskException -= action; 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() async UniTask InException1()
{ {
await UniTask.Yield(); await UniTask.Yield();