Skip to content

Commit 5684054

Browse files
committed
fix(sleep) use interruptible sleep function
1 parent 0dfc4c7 commit 5684054

1 file changed

Lines changed: 49 additions & 4 deletions

File tree

lib/resty/timer.lua

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,60 @@ local timer_id = 0
1616
local now = ngx.now
1717
local sleep = ngx.sleep
1818
local exiting = ngx.worker.exiting
19+
local min = math.min
1920

2021
local KEY_PREFIX = "[lua-resty-timer]"
2122
local LOG_PREFIX = "[resty-timer] "
2223
local CANCEL_GC = "GC"
2324
local CANCEL_SYSTEM = "SYSTEM"
2425
local CANCEL_USER = "USER"
2526

27+
local sleepx do
28+
local SLEEP_BLOCK_SIZE = 5
29+
30+
-- create a 10yr timer only called with `premature` set. The callback will
31+
-- release a global semaphore to wake up sleeping threads
32+
local sema = assert(require("ngx.semaphore").new())
33+
assert(timer_at(10*365*24*60*60, function()
34+
sema:post(math.huge)
35+
end))
36+
37+
--- A `sleep` function that exits early on system exit. The same as `ngx.sleep`
38+
-- except that it will be interrupted when the current worker starts exiting.
39+
-- @param delay same as `ngx.sleep()`; delay in seconds.
40+
-- @return results of `ngx.worker.exiting()`
41+
-- @usage if sleepx(5) then
42+
-- -- sleep was interrupted, exit now
43+
-- return nil, "exiting"
44+
-- end
45+
--
46+
-- -- do stuff
47+
function sleepx(delay)
48+
if type(delay) ~= "number" then
49+
error("Bad argument #1, expected number, got " .. type(delay), 2)
50+
end
51+
52+
if delay <= 0 then
53+
sleep(delay)
54+
return exiting()
55+
end
56+
57+
-- this doesn't work
58+
-- see https://github.com/openresty/lua-resty-core/issues/337
59+
-- sema:wait(delay)
60+
-- return exiting()
61+
62+
-- fall-back to sleeping in SLEEP_BLOCK_SIZE sec chunks
63+
local t = now()
64+
local exit_at = t + delay
65+
while exit_at > t and not exiting() do
66+
sleep(min(SLEEP_BLOCK_SIZE, exit_at - t))
67+
t = now()
68+
end
69+
return exiting()
70+
end
71+
end
72+
2673

2774

2875
--- Cancel the timer.
@@ -141,10 +188,7 @@ local function handler(premature, id)
141188
end
142189

143190
-- existing timer recurring, so keep this thread alive and just sleep
144-
if not exiting() then
145-
sleep(next_interval)
146-
end
147-
premature = exiting()
191+
premature = sleepx(next_interval)
148192
end -- while
149193
end
150194

@@ -340,6 +384,7 @@ end
340384
return setmetatable(
341385
{
342386
new = new,
387+
sleepx = sleepx,
343388
CANCEL_GC = CANCEL_GC,
344389
CANCEL_SYSTEM = CANCEL_SYSTEM,
345390
CANCEL_USER = CANCEL_USER,

0 commit comments

Comments
 (0)