Coroutine Threads are not garbage collected and cannot be abandoned
Brought to you by:
ian_farmer,
jim_roseborough
In Lua the following snippet works perfectly, in Luaj it rapidly produces an OutOfMemoryError.
:::lua
while true do
local cor = coroutine.wrap(function() coroutine.yield(false) end)
cor()
end
The documentation in LuaThread and CoroutineLib is not entirely consistent about whether this is expected behaviour.
A simple use-case can be found at How can I abandon a LuaJ coroutine LuaThread?
Here are a couple of bandaids I have tried:
:::java
static final class abandon extends LibFunction {
public LuaValue call(LuaValue t) {
LuaThread.State s = t.checkthread().state;
if(s.status == LuaThread.STATUS_RUNNING || s.status == LuaThread.STATUS_NORMAL) {
return LuaValue.FALSE;
}
synchronized(s) {
s.status = LuaThread.STATUS_DEAD;
s.notify();
return LuaValue.TRUE;
}
}
}
...
globals.get("coroutine").set("abandon", new abandon());
In any case forcibly destroying a coroutine is a Bad Idea and shouldn't be necessary.
I've found a much cleaner way to achieve this, but it's library invasive. The following (or similar, not fully tested) would allow users to cleanly dispose of coroutines that have been suspended and will never be resumed.
This is not a very complete treatment of the problem, but it does provide a neat and specific mechanism to get around it.
LuaThread.State
..