@@ -14,58 +14,59 @@ local anchor_registry = {}
1414local gc_registry = setmetatable ({},{ __mode = " v" })
1515local timer_id = 0
1616local now = ngx .now
17- local sleep = ngx .sleep
17+ local ngx_sleep = ngx .sleep
1818local exiting = ngx .worker .exiting
19- local min = math.min
2019
2120local KEY_PREFIX = " [lua-resty-timer]"
2221local LOG_PREFIX = " [resty-timer] "
2322local CANCEL_GC = " GC"
2423local CANCEL_SYSTEM = " SYSTEM"
2524local CANCEL_USER = " USER"
2625
27- local sleepx do
28- local SLEEP_BLOCK_SIZE = 5
29-
26+ local sleep do
3027 -- create a 10yr timer only called with `premature` set. The callback will
3128 -- release a global semaphore to wake up sleeping threads
3229 local sema = assert (require (" ngx.semaphore" ).new ())
3330 assert (timer_at (10 * 365 * 24 * 60 * 60 , function ()
3431 sema :post (math.huge )
32+
33+ -- TODO: remove the below log line, it's an ugly hack around semaphores
34+ -- not being released properly, an Openresty bug.
35+ -- See https://github.com/openresty/lua-resty-core/issues/337
36+ ngx .timer .at (0 , function ()
37+ ngx .log (ngx .WARN ," please ignore, just generating IO, see https://github.com/openresty/lua-resty-core/issues/337" )
38+ end )
3539 end ))
3640
3741 --- A `sleep` function that exits early on system exit. The same as `ngx.sleep`
3842 -- except that it will be interrupted when the current worker starts exiting.
3943 -- @param delay same as `ngx.sleep()`; delay in seconds.
4044 -- @return results of `ngx.worker.exiting()`
41- -- @usage if sleepx (5) then
45+ -- @usage if sleep (5) then
4246 -- -- sleep was interrupted, exit now
4347 -- return nil, "exiting"
4448 -- end
4549 --
4650 -- -- do stuff
47- function sleepx (delay )
51+ function sleep (delay )
4852 if type (delay ) ~= " number" then
4953 error (" Bad argument #1, expected number, got " .. type (delay ), 2 )
5054 end
5155
5256 if delay <= 0 then
53- sleep (delay )
57+ ngx_sleep (delay )
5458 return exiting ()
5559 end
5660
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 ()
61+ local _ , err = sema :wait (delay )
62+ if err == " timeout" then
63+ return false
6864 end
65+
66+ if err then
67+ ngx .log (ngx .ERR , " waiting for semaphore failed: " , err )
68+ end
69+
6970 return exiting ()
7071 end
7172end
@@ -188,7 +189,7 @@ local function handler(premature, id)
188189 end
189190
190191 -- existing timer recurring, so keep this thread alive and just sleep
191- premature = sleepx (next_interval )
192+ premature = sleep (next_interval )
192193 end -- while
193194end
194195
384385return setmetatable (
385386 {
386387 new = new ,
387- sleepx = sleepx ,
388+ sleep = sleep ,
388389 CANCEL_GC = CANCEL_GC ,
389390 CANCEL_SYSTEM = CANCEL_SYSTEM ,
390391 CANCEL_USER = CANCEL_USER ,
0 commit comments