From 49e7dac558178e6200bc5886db3ef28c73d5edd9 Mon Sep 17 00:00:00 2001 From: Thijs Schreijer Date: Mon, 7 Apr 2025 10:43:30 +0200 Subject: fix(readkey): if sleep fails return the error (#60) --- CHANGELOG.md | 4 ++++ spec/04-term_spec.lua | 26 ++++++++++++++++++++++++++ system/init.lua | 9 ++++++--- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c9e15e..2fd09d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,10 @@ The scope of what is covered by the version number excludes: ## Version history +### version 0.6.0, unreleased + +- Fix: when sleep returns an error, pass that on in `readkey`. + ### version 0.5.1, released 12-Mar-2025 - Fix: on older unixes with glibc < 2.25, fall back to `/dev/urandom` diff --git a/spec/04-term_spec.lua b/spec/04-term_spec.lua index 907f903..b3de461 100644 --- a/spec/04-term_spec.lua +++ b/spec/04-term_spec.lua @@ -855,6 +855,32 @@ describe("Terminal:", function() assert.is.near(1, timing, 0.5) -- this also works for MacOS in CI end) + + it("calls flseep to execute the sleep", function() + setbuffer("") + + local sleep_called = false + local mysleep = function() + sleep_called = true + end + + system.readkey(0.01, mysleep) + assert.is_true(sleep_called) + end) + + + it("returns errors by fsleep", function() + setbuffer("") + + local mysleep = function() + return nil, "boom!" + end + + local ok, err = system.readkey(1, mysleep) + assert.is.falsy(ok) + assert.equals("boom!", err) + end) + end) diff --git a/system/init.lua b/system/init.lua index a81978e..28fe65c 100644 --- a/system/init.lua +++ b/system/init.lua @@ -236,10 +236,10 @@ do -- Using `system.readansi` is preferred over this function. Since this function can leave stray/invalid -- byte-sequences in the input buffer, while `system.readansi` reads full ANSI and UTF8 sequences. -- @tparam number timeout the timeout in seconds. - -- @tparam[opt=system.sleep] function fsleep the function to call for sleeping. + -- @tparam[opt=system.sleep] function fsleep the function to call for sleeping; `ok, err = fsleep(secs)` -- @treturn[1] byte the byte value that was read. -- @treturn[2] nil if no key was read - -- @treturn[2] string error message; `"timeout"` if the timeout was reached. + -- @treturn[2] string error message when the timeout was reached (`"timeout"`), or if `sleep` failed. function system.readkey(timeout, fsleep) if type(timeout) ~= "number" then error("arg #1 to readkey, expected timeout in seconds, got " .. type(timeout), 2) @@ -248,7 +248,10 @@ do local interval = 0.0125 local key = system._readkey() while key == nil and timeout > 0 do - (fsleep or system.sleep)(math.min(interval, timeout)) + local ok, err = (fsleep or system.sleep)(math.min(interval, timeout)) + if not ok then + return nil, err + end timeout = timeout - interval interval = math.min(0.2, interval * 2) key = system._readkey() -- cgit v1.2.3-55-g6feb