Module corowatch
Module to watch coroutine executiontime.
Coroutines running too long without
yielding can be killed to prevent them from locking the Lua state.
The module uses LuaSocket
to get the time (socket.gettime
function). If you
do not want that, override the coroutine.gettime
method with your own
implementation.
Info:
- Copyright: Copyright (c) 2013-2022 Thijs Schreijer
- License: MIT, see LICENSE.md.
- Author: Thijs Schreijer
Functions
create (f) | This is the same as the regular coroutine.create, except that when the running coroutine is watched, then children spawned will also be watched with the same settings. |
export ([t]) | Export the corowatch functions to an external table, or the global environment. |
gettime () | returns current time in seconds. |
resume (coro, ...) | This is the same as the regular coroutine.resume. |
sethook (coro, ...) | This is the same as the regular debug.sethook, except that when trying to set a hook on a coroutine that is being watched, if will throw an error. |
status (coro) | This is the same as the regular coroutine.status. |
watch (coro, tkilllimit, twarnlimit, cb[, hookcount=10000]) | Protects a coroutine from running too long without yielding. |
wrap (f) | This is the same as the regular coroutine.wrap, except that when the running coroutine is watched, then children spawned will also be watched with the same settings. |
wrapf (f, tkilllimit, twarnlimit, cb[, hookcount=10000]) | This is the same as the regular coroutine.wrap, except that the coroutine created is watched according to the parameters provided, and not according to the watch parameters of the currently running coroutine. |
yield (...) | This is the same as the regular coroutine.yield. |
Functions
- create (f)
-
This is the same as the regular coroutine.create, except that when the running
coroutine is watched, then children spawned will also be watched with the same
settings.
Parameters:
- f see coroutine.create
- export ([t])
-
Export the corowatch functions to an external table, or the global environment.
The functions exported are create, yield, resume, status, wrap, and wrapf. The standard
coroutine.running will be added if there is no
running
value in the table yet. So basically it exports a complete coroutine table + wrapf. If the provided table contains subtables coroutine and/or debug then it is assumed to be a function/global environment and sethook will be exported as well (exports will then go into the two subtables)Parameters:
- t table table to which to export the coroutine functions. (optional)
Returns:
-
the table provided, or a new table if non was provided, with the exported functions
Usage:
-- monkey patch global environment, both coroutine and debug tables require("corowatch").export(_G)
- gettime ()
-
returns current time in seconds. If not overridden, it will require
luasocket
and usesocket.gettime
to get the current time. - resume (coro, ...)
-
This is the same as the regular coroutine.resume.
Parameters:
- coro see coroutine.resume
- ... see coroutine.resume
- sethook (coro, ...)
-
This is the same as the regular debug.sethook, except that when trying to set a
hook on a coroutine that is being watched, if will throw an error.
Parameters:
- coro see debug.sethook
- ... see debug.sethook
- status (coro)
-
This is the same as the regular coroutine.status.
Parameters:
- coro see coroutine.status
- watch (coro, tkilllimit, twarnlimit, cb[, hookcount=10000])
-
Protects a coroutine from running too long without yielding.
The callback has 1 parameter (string value being either "warn" or "kill"), but runs
on the coroutine that is subject of the warning. If the "warn" callback returns a
truthy value (neither
false
, nornil
) then the timeouts for kill and warn limits will be reset (buying more time for the coroutine to finish its business).The
hookcount
default of 10000 will ensure offending coroutines are caught with limited performance impact. To better narrow down any offending code that takes too long, this can be set to a lower value (eg. set it to 1, and it will break right after the instruction that tripped the limit). But the smaller the value, the higher the performance cost.NOTE: the callback runs inside a debughook.
Parameters:
- coro coroutine or nil coroutine to be protected, defaults to the currently running routine
- tkilllimit number or nil time in seconds it is allowed to run without yielding
- twarnlimit
number or nil
time in seconds it is allowed before
cb
is called (must be smaller thantkilllimit
) - cb function or nil callback executed when the kill or warn limit is reached.
- hookcount
number
the hookcount to use (every
x
number of VM instructions check the limits) (default 10000)
Returns:
-
coro
- wrap (f)
-
This is the same as the regular coroutine.wrap, except that when the running
coroutine is watched, then children spawned will also be watched with the same
settings. To set sepecific settings for watching use
coroutine.wrapf
.Parameters:
- f see coroutine.wrap
See also:
- wrapf (f, tkilllimit, twarnlimit, cb[, hookcount=10000])
-
This is the same as the regular coroutine.wrap, except that the coroutine created
is watched according to the parameters provided, and not according to the watch
parameters of the currently running coroutine.
Parameters:
- f function function to wrap
- tkilllimit number or nil see watch
- twarnlimit number or nil see watch
- cb function or nil see watch
- hookcount number see watch (default 10000)
See also:
- yield (...)
-
This is the same as the regular coroutine.yield.
Parameters:
- ... see coroutine.yield