From 15e1e5ca43d2f16165e6ae8ff0b318b0c279a1f9 Mon Sep 17 00:00:00 2001 From: Kevin Harder Date: Wed, 20 May 2026 12:45:17 -0500 Subject: [PATCH] Fixes #5349. Ignore non-readable poll events Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Drivers/UnixHelpers/UnixIOHelper.cs | 15 +++- .../Drivers/UnixIOHelperTests.cs | 85 +++++++++++++++++++ 2 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 Tests/UnitTestsParallelizable/Drivers/UnixIOHelperTests.cs diff --git a/Terminal.Gui/Drivers/UnixHelpers/UnixIOHelper.cs b/Terminal.Gui/Drivers/UnixHelpers/UnixIOHelper.cs index 6126fe6bc4..ecaa7600e7 100644 --- a/Terminal.Gui/Drivers/UnixHelpers/UnixIOHelper.cs +++ b/Terminal.Gui/Drivers/UnixHelpers/UnixIOHelper.cs @@ -236,7 +236,20 @@ public static bool IsInputAvailable (Pollfd [] pollMap, int timeoutMs = 0) { int n = poll (pollMap, (uint)pollMap.Length, timeoutMs); - return n > 0; + if (n <= 0) + { + return false; + } + + foreach (Pollfd pollfd in pollMap) + { + if ((pollfd.revents & (short)Condition.PollIn) != 0) + { + return true; + } + } + + return false; } catch { diff --git a/Tests/UnitTestsParallelizable/Drivers/UnixIOHelperTests.cs b/Tests/UnitTestsParallelizable/Drivers/UnixIOHelperTests.cs new file mode 100644 index 0000000000..e3d91b0900 --- /dev/null +++ b/Tests/UnitTestsParallelizable/Drivers/UnixIOHelperTests.cs @@ -0,0 +1,85 @@ +using System.Runtime.InteropServices; +using Terminal.Gui.Drivers; + +namespace DriverTests; + +/// +/// Tests for polling semantics on Unix-like platforms. +/// +[Collection ("Driver Tests")] +public class UnixIOHelperTests +{ + [DllImport ("libc", SetLastError = true)] + private static extern int pipe (int [] pipefd); + + [DllImport ("libc", SetLastError = true)] + private static extern int close (int fd); + + [Fact] + // Copilot + public void IsInputAvailable_ReturnsTrue_WhenPollReportsReadableData () + { + if (!OperatingSystem.IsLinux () && !OperatingSystem.IsMacOS () && !OperatingSystem.IsFreeBSD ()) + { + return; + } + + int [] pipeFds = new int [2]; + Assert.Equal (0, pipe (pipeFds)); + + try + { + byte [] payload = [0x41]; + Assert.Equal (1, UnixIOHelper.write (pipeFds [1], payload, payload.Length)); + + UnixIOHelper.Pollfd [] pollMap = + [ + new () + { + fd = pipeFds [0], + events = (short)UnixIOHelper.Condition.PollIn + } + ]; + + Assert.True (UnixIOHelper.IsInputAvailable (pollMap, 0)); + } + finally + { + close (pipeFds [0]); + close (pipeFds [1]); + } + } + + [Fact] + // Copilot + public void IsInputAvailable_ReturnsFalse_WhenPollReportsNonReadableEvent () + { + if (!OperatingSystem.IsLinux () && !OperatingSystem.IsMacOS () && !OperatingSystem.IsFreeBSD ()) + { + return; + } + + int [] pipeFds = new int [2]; + Assert.Equal (0, pipe (pipeFds)); + + try + { + Assert.Equal (0, close (pipeFds [0])); + + UnixIOHelper.Pollfd [] pollMap = + [ + new () + { + fd = pipeFds [0], + events = (short)UnixIOHelper.Condition.PollIn + } + ]; + + Assert.False (UnixIOHelper.IsInputAvailable (pollMap, 0)); + } + finally + { + close (pipeFds [1]); + } + } +}