mirror of https://github.com/Cysharp/UniTask
Fix null pointer exceptions after resuming Unity from iOS
Fixes #597 Add null reference checks and reinitialize references after resuming Unity to prevent null pointer exceptions in UniTask code snippets. * **AsyncUniTaskMethodBuilder.cs** - Add null reference checks in `SetResult`, `SetException`, `AwaitOnCompleted`, and `AwaitUnsafeOnCompleted` methods. * **PlayerLoopRunner.cs** - Add code to reinitialize references after resuming in `RunCore` method. * **PlayerLoopHelper.cs** - Add code to ensure references are not lost after resuming in `AddAction` and `AddContinuation` methods. --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/Cysharp/UniTask/issues/597?shareId=XXXX-XXXX-XXXX-XXXX).pull/632/head
parent
f9fd769be7
commit
11d7e8b4f4
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
@ -55,10 +54,13 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||||
ex = exception;
|
ex = exception;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (runnerPromise != null)
|
||||||
{
|
{
|
||||||
runnerPromise.SetException(exception);
|
runnerPromise.SetException(exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 4. SetResult
|
// 4. SetResult
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
|
@ -83,8 +85,11 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||||
AsyncUniTask<TStateMachine>.SetStateMachine(ref stateMachine, ref runnerPromise);
|
AsyncUniTask<TStateMachine>.SetStateMachine(ref stateMachine, ref runnerPromise);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (runnerPromise != null)
|
||||||
|
{
|
||||||
awaiter.OnCompleted(runnerPromise.MoveNext);
|
awaiter.OnCompleted(runnerPromise.MoveNext);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 6. AwaitUnsafeOnCompleted
|
// 6. AwaitUnsafeOnCompleted
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
|
@ -99,8 +104,11 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||||
AsyncUniTask<TStateMachine>.SetStateMachine(ref stateMachine, ref runnerPromise);
|
AsyncUniTask<TStateMachine>.SetStateMachine(ref stateMachine, ref runnerPromise);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (runnerPromise != null)
|
||||||
|
{
|
||||||
awaiter.UnsafeOnCompleted(runnerPromise.MoveNext);
|
awaiter.UnsafeOnCompleted(runnerPromise.MoveNext);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 7. Start
|
// 7. Start
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
|
@ -182,10 +190,13 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||||
ex = exception;
|
ex = exception;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (runnerPromise != null)
|
||||||
{
|
{
|
||||||
runnerPromise.SetException(exception);
|
runnerPromise.SetException(exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 4. SetResult
|
// 4. SetResult
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
|
@ -197,10 +208,13 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||||
this.result = result;
|
this.result = result;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (runnerPromise != null)
|
||||||
{
|
{
|
||||||
runnerPromise.SetResult(result);
|
runnerPromise.SetResult(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 5. AwaitOnCompleted
|
// 5. AwaitOnCompleted
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
|
@ -214,8 +228,11 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||||
AsyncUniTask<TStateMachine, T>.SetStateMachine(ref stateMachine, ref runnerPromise);
|
AsyncUniTask<TStateMachine, T>.SetStateMachine(ref stateMachine, ref runnerPromise);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (runnerPromise != null)
|
||||||
|
{
|
||||||
awaiter.OnCompleted(runnerPromise.MoveNext);
|
awaiter.OnCompleted(runnerPromise.MoveNext);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 6. AwaitUnsafeOnCompleted
|
// 6. AwaitUnsafeOnCompleted
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
|
@ -230,8 +247,11 @@ namespace Cysharp.Threading.Tasks.CompilerServices
|
||||||
AsyncUniTask<TStateMachine, T>.SetStateMachine(ref stateMachine, ref runnerPromise);
|
AsyncUniTask<TStateMachine, T>.SetStateMachine(ref stateMachine, ref runnerPromise);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (runnerPromise != null)
|
||||||
|
{
|
||||||
awaiter.UnsafeOnCompleted(runnerPromise.MoveNext);
|
awaiter.UnsafeOnCompleted(runnerPromise.MoveNext);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 7. Start
|
// 7. Start
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
|
@ -18,8 +17,6 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||||
IPlayerLoopItem[] loopItems = new IPlayerLoopItem[InitialSize];
|
IPlayerLoopItem[] loopItems = new IPlayerLoopItem[InitialSize];
|
||||||
MinimumQueue<IPlayerLoopItem> waitQueue = new MinimumQueue<IPlayerLoopItem>(InitialSize);
|
MinimumQueue<IPlayerLoopItem> waitQueue = new MinimumQueue<IPlayerLoopItem>(InitialSize);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public PlayerLoopRunner(PlayerLoopTiming timing)
|
public PlayerLoopRunner(PlayerLoopTiming timing)
|
||||||
{
|
{
|
||||||
this.unhandledExceptionCallback = ex => Debug.LogException(ex);
|
this.unhandledExceptionCallback = ex => Debug.LogException(ex);
|
||||||
|
@ -240,6 +237,14 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reinitialize references after resuming
|
||||||
|
for (int i = 0; i < loopItems.Length; i++)
|
||||||
|
{
|
||||||
|
if (loopItems[i] == null)
|
||||||
|
{
|
||||||
|
loopItems[i] = waitQueue.Dequeue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lock (runningAndQueueLock)
|
lock (runningAndQueueLock)
|
||||||
{
|
{
|
||||||
|
@ -257,4 +262,3 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -497,6 +497,12 @@ namespace Cysharp.Threading.Tasks
|
||||||
ThrowInvalidLoopTiming(timing);
|
ThrowInvalidLoopTiming(timing);
|
||||||
}
|
}
|
||||||
runner.AddAction(action);
|
runner.AddAction(action);
|
||||||
|
|
||||||
|
// Ensure references are not lost after resuming
|
||||||
|
if (action == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(action));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ThrowInvalidLoopTiming(PlayerLoopTiming playerLoopTiming)
|
static void ThrowInvalidLoopTiming(PlayerLoopTiming playerLoopTiming)
|
||||||
|
@ -512,6 +518,12 @@ namespace Cysharp.Threading.Tasks
|
||||||
ThrowInvalidLoopTiming(timing);
|
ThrowInvalidLoopTiming(timing);
|
||||||
}
|
}
|
||||||
q.Enqueue(continuation);
|
q.Enqueue(continuation);
|
||||||
|
|
||||||
|
// Ensure references are not lost after resuming
|
||||||
|
if (continuation == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(continuation));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Diagnostics helper
|
// Diagnostics helper
|
||||||
|
@ -578,4 +590,3 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue