From b2901ce8efa050da00e0f3a73f3be9bf9402deea Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Wed, 12 Jul 2023 11:52:06 +0100 Subject: ash: fix 'read' shell built-in (2) Enabling polling in the previous commit resulted in the following incorrect behaviour: { echo -n te; sleep 3; echo st; } | (read -t 1 x; echo "$x") An empty "$x" is echoed immediately, not after 1 second. { echo -n te; sleep 1; echo st; } | (read -t 3 x; echo "$x") An empty "$x" is echoed immediately. "test" should be echoed after 1 second. This arises because poll(2) from gnulib is unable to handle anonymous pipes properly due do deficiencies in Microsoft Windows. These have been acknowledged and fixed in relation to select(2): https://lists.gnu.org/archive/html/bug-gnulib/2014-06/msg00051.html Apply a similar fix to poll(2). Costs 104-156 bytes. --- win32/poll.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/win32/poll.c b/win32/poll.c index dd3b2d1cb..4b825c5cc 100644 --- a/win32/poll.c +++ b/win32/poll.c @@ -469,6 +469,9 @@ poll (struct pollfd *pfd, nfds_t nfd, int timeout) MSG msg; int rc = 0; nfds_t i; + DWORD real_timeout = 0; + int save_timeout = timeout; + clock_t tend = clock () + timeout; if (nfd > INT_MAX || timeout < -1) { @@ -480,6 +483,14 @@ poll (struct pollfd *pfd, nfds_t nfd, int timeout) hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); restart: + /* How much is left to wait? */ + timeout = save_timeout; + if (timeout != INFTIM) + { + clock_t now = clock (); + real_timeout = tend > now ? tend - now : 0; + } + handle_array[0] = hEvent; nhandles = 1; FD_ZERO (&rfds); @@ -620,7 +631,7 @@ restart: rc++; } - if (!rc && timeout == INFTIM) + if (!rc && (save_timeout == INFTIM || (real_timeout != 0 && nhandles > 1))) { SleepEx (1, TRUE); goto restart; -- cgit v1.2.3-55-g6feb