Skip to content

Commit 047bb8e

Browse files
authored
FIX: An infinite loop in InputSystemUIInputModule was causing an editor / player hang (#2102)
1 parent 1e20672 commit 047bb8e

File tree

2 files changed

+21
-13
lines changed

2 files changed

+21
-13
lines changed

Packages/com.unity.inputsystem/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ however, it has to be formatted properly to pass verification tests.
3838
- Fixed an issue where batch jobs would fail with "Error: Error building Player because scripts are compiling" if a source generated .inputactions asset is out of sync with its generated source code (ISXB-1300).
3939
- Fixed multiple `OnScreenStick` Components that does not work together when using them simultaneously in isolation mode. [ISXB-813](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-813)
4040
- Fixed an issue in input actions editor window that caused certain fields in custom input composite bindings to require multiple clicks to action / focus. [ISXB-1171](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1171)
41+
- Fixed an editor/player hang in `InputSystemUIInputModule` due to an infinite loop. This was caused by the assumption that `RemovePointerAtIndex` would _always_ successfully remove the pointer, which is not the case with touch based pointers. [ISXB-1258](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1258)
4142

4243
### Changed
4344
- Changed location of the link xml file (code stripping rules), from a temporary directory to the project Library folder (ISX-2140).

Packages/com.unity.inputsystem/InputSystem/Plugins/UI/InputSystemUIInputModule.cs

+20-13
Original file line numberDiff line numberDiff line change
@@ -1662,9 +1662,11 @@ protected override void OnDisable()
16621662

16631663
private void ResetPointers()
16641664
{
1665-
var numPointers = m_PointerStates.length;
1666-
for (var i = 0; i < numPointers; ++i)
1667-
SendPointerExitEventsAndRemovePointer(0);
1665+
for (var i = 0; i < m_PointerStates.length; ++i)
1666+
{
1667+
if (SendPointerExitEventsAndRemovePointer(i))
1668+
--i;
1669+
}
16681670

16691671
m_CurrentPointerId = -1;
16701672
m_CurrentPointerIndex = -1;
@@ -2021,24 +2023,26 @@ private int AllocatePointer(int pointerId, int displayIndex, int touchId, UIPoin
20212023
return m_PointerStates.AppendWithCapacity(new PointerModel(eventData));
20222024
}
20232025

2024-
private void SendPointerExitEventsAndRemovePointer(int index)
2026+
// Returns true if the pointer was successfully removed (ISXB-1258)
2027+
private bool SendPointerExitEventsAndRemovePointer(int index)
20252028
{
20262029
var eventData = m_PointerStates[index].eventData;
20272030
if (eventData.pointerEnter != null)
20282031
ProcessPointerMovement(eventData, null);
20292032

2030-
RemovePointerAtIndex(index);
2033+
return RemovePointerAtIndex(index);
20312034
}
20322035

2033-
private void RemovePointerAtIndex(int index)
2036+
private bool RemovePointerAtIndex(int index)
20342037
{
20352038
Debug.Assert(m_PointerStates[index].eventData.pointerEnter == null, "Pointer should have exited all objects before being removed");
20362039

20372040
// We don't want to release touch pointers on the same frame they are released (unpressed). They get cleaned up one frame later in Process()
20382041
ref var state = ref GetPointerStateForIndex(index);
20392042
if (state.pointerType == UIPointerType.Touch && (state.leftButton.isPressed || state.leftButton.wasReleasedThisFrame))
20402043
{
2041-
return;
2044+
// The pointer was not removed
2045+
return false;
20422046
}
20432047

20442048
// Retain event data so that we can reuse the event the next time we allocate a PointerModel record.
@@ -2086,6 +2090,8 @@ private void RemovePointerAtIndex(int index)
20862090
m_PointerStates.firstValue.eventData = eventData;
20872091
else
20882092
m_PointerStates.additionalValues[m_PointerStates.length - 1].eventData = eventData;
2093+
2094+
return true;
20892095
}
20902096

20912097
// Remove any pointer that no longer has the ability to point.
@@ -2100,8 +2106,9 @@ private void PurgeStalePointers()
21002106
!HaveControlForDevice(device, trackedDevicePosition) &&
21012107
!HaveControlForDevice(device, trackedDeviceOrientation)))
21022108
{
2103-
SendPointerExitEventsAndRemovePointer(i);
2104-
--i;
2109+
// Only decrement 'i' if the pointer was successfully removed
2110+
if (SendPointerExitEventsAndRemovePointer(i))
2111+
--i;
21052112
}
21062113
}
21072114

@@ -2310,8 +2317,8 @@ private void FilterPointerStatesByType()
23102317
}
23112318
if (m_PointerStates[i].pointerType != UIPointerType.MouseOrPen && m_PointerStates[i].pointerType != UIPointerType.Touch || (m_PointerStates[i].pointerType == UIPointerType.Touch && !state.leftButton.isPressed && !state.leftButton.wasReleasedThisFrame))
23122319
{
2313-
SendPointerExitEventsAndRemovePointer(i);
2314-
--i;
2320+
if (SendPointerExitEventsAndRemovePointer(i))
2321+
--i;
23152322
}
23162323
}
23172324
}
@@ -2322,8 +2329,8 @@ private void FilterPointerStatesByType()
23222329
{
23232330
if (m_PointerStates[i].pointerType == UIPointerType.MouseOrPen)
23242331
{
2325-
SendPointerExitEventsAndRemovePointer(i);
2326-
--i;
2332+
if (SendPointerExitEventsAndRemovePointer(i))
2333+
--i;
23272334
}
23282335
}
23292336
}

0 commit comments

Comments
 (0)