Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions Assets/Tests/InputSystem/CoreTests_Devices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4384,6 +4384,28 @@ public void Devices_CanSetPollingFrequency()
Assert.That(InputSystem.pollingFrequency, Is.EqualTo(120).Within(0.000001));
}

[Test]
[Category("Devices")]
public void Devices_CannotSetPollingFrequencyToNonFiniteValue()
{
// A plain `value <= 0` guard misses NaN (which compares false against everything) and
// +Infinity, leaving pollingFrequency stuck at that value on every read. (ISX-2837)
InputSystem.pollingFrequency = 120;

Assert.That(() => InputSystem.pollingFrequency = float.NaN, Throws.ArgumentException);

// The native backend does accept +Infinity, as "poll continuously". This public API
// deliberately does not - it pins a core, and is far more likely to be a `1f/0f` accident
// at the call site than a deliberate choice.
Assert.That(() => InputSystem.pollingFrequency = float.PositiveInfinity, Throws.ArgumentException);
Assert.That(() => InputSystem.pollingFrequency = float.NegativeInfinity, Throws.ArgumentException);
Assert.That(() => InputSystem.pollingFrequency = 0f, Throws.ArgumentException);
Assert.That(() => InputSystem.pollingFrequency = -1f, Throws.ArgumentException);

// A rejected assignment must leave the previous value untouched.
Assert.That(InputSystem.pollingFrequency, Is.EqualTo(120).Within(0.000001));
}

#if UNITY_INPUT_SYSTEM_PLATFORM_POLLING_FREQUENCY
[Test]
[Category("Devices")]
Expand Down
1 change: 1 addition & 0 deletions Packages/com.unity.inputsystem/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

### Fixed

- Fixed `InputSystem.pollingFrequency` accepting non-finite values. Both `NaN` and `+Infinity` slipped past the `value <= 0` guard - `NaN` left the property returning `NaN` on every read and disabled background polling, while `+Infinity` set the backend to poll continuously and occupy a CPU core. Since both are almost always the result of an arithmetic accident at the call site (`0f/0f` and `1f/0f` respectively), they are now rejected with an `ArgumentException`. [ISX-2837](https://jira.unity3d.com/browse/ISX-2837)
- Fixed the "Supported Devices" list in the Input System Package Settings sitting flush against the panel edge with no left/right margin, unlike the surrounding fields; it is now inset to line up with the other settings controls [UUM-150207](https://issuetracker.unity3d.com/product/unity/issues/guid/UUM-150207)
- Fixed the Inspector help button for a selected `.inputactions` asset ("Open Reference for Input Action Importer") opening a missing documentation page; it now links to the Action Assets manual page [UUM-149518](https://issuetracker.unity3d.com/product/unity/issues/guid/UUM-149518)
- Fixed an `OverflowException` when creating a control scheme (or other named item) whose all-numeric name exceeds `Int32.MaxValue`, which previously discarded the entered name and fell back to the default [UUM-145766](https://issuetracker.unity3d.com/product/unity/issues/guid/UUM-145766)
Expand Down
14 changes: 11 additions & 3 deletions Packages/com.unity.inputsystem/InputSystem/Runtime/InputManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,17 @@ public float pollingFrequency

set
{
////REVIEW: allow setting to zero to turn off polling altogether?
if (value <= 0)
throw new ArgumentException("Polling frequency must be greater than zero", "value");
// Non-finite values almost always arrive by accident - `0f/0f` gives NaN and `1f/0f`
// gives +Infinity - and both slip past a plain `value <= 0` check. NaN gets cached
// and read back forever. +Infinity means continuous polling in the native backend,
// which leaves the polling thread nothing to wait on and pins a core. Neither is
// something a public setter should accept. Zero is likewise supported by the native
// backend, where it disables polling outright, but is not exposed here - silently
// stopping all polled-device input from a frequency setter is a footgun rather than
// a discoverable off switch.
// (float.IsFinite is unavailable on netstandard2.0.)
if (value <= 0 || float.IsNaN(value) || float.IsInfinity(value))
throw new ArgumentException("Polling frequency must be a finite value greater than zero", "value");

#if UNITY_INPUT_SYSTEM_PLATFORM_POLLING_FREQUENCY
m_Runtime.pollingFrequency = value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1337,7 +1337,13 @@ public static event InputDeviceFindControlLayoutDelegate onFindLayoutForDevice
///
/// Also note that the polling frequency applies to all devices that are polled. It is not possible
/// to set polling frequency on a per-device basis.
///
/// Only finite values greater than zero are accepted. Non-finite values are rejected rather than
/// passed through, as they are almost always the result of an arithmetic accident at the call site
/// (<c>0f/0f</c> yields <c>NaN</c>, <c>1f/0f</c> yields <c>+Infinity</c>) and would otherwise leave
/// polling in an unusable state.
/// </remarks>
/// <exception cref="ArgumentException">Value is not a finite number greater than zero.</exception>
public static float pollingFrequency
{
get => s_Manager.pollingFrequency;
Expand Down
Loading