Before there was no way to force a lua coroutine or state to stop executing. Meaning scripts could easily crash the application or etc.
110 Added the method pause_execution to LuaCoroutine. Which would call lua_yield in a hook it sets at the time the function is called. The hook would only run once.
112 Added the methods interrupt_execution and kill. Both of which would create a hook in the same manner as before. interrupt_execution would raise an error one time. Kill would do the same, but never remove its hook.
The issue
The intent was that the lua state would be executing on a separate thread when these methods were called. However accessing or modifying the lua state on multiple threads is not safe.
The fix
Instead of having predefined hooks and helper methods as before. This PR adds the ability for the user to create hooks from gdScript. It also adds the ability to yield the lua state from within these hooks. Using yield_state. Aswell as retrieving the current running corouitne from the parent LuaAPI object via get_running_coroutine.
Example
extends Node2D
var lua: LuaAPI
var coroutine: LuaCoroutine
func _lua_hook(lua: LuaAPI, event: int, line: int):
var co: LuaCoroutine = lua.get_running_coroutine()
co.yield_state([1])
func _ready():
lua = LuaAPI.new()
# Despite the name, this is not like a OS coroutine. It is a coroutine.
coroutine = lua.new_coroutine()
coroutine.set_hook(_lua_hook, LuaAPI.HOOK_MASK_COUNT, 4)
coroutine.load_string("
while true do
print('Hello world!')
end
")
var yieldTime = 0
var timeSince = 0
var goodBye = false
func _process(delta):
timeSince += delta
# If the coroutine has finished executing or if not enough time has passed, do not resume the coroutine.
if coroutine.is_done() || timeSince <= yieldTime:
if !goodBye:
lua.do_string("""
for i = 0,10,1 do
print('Good Bye World!')
end
""")
goodBye=true
return
goodBye=false
# coroutine.resume will either return a LuaError or an Array.
var ret = coroutine.resume()
if ret is LuaError:
print("ERROR %d: " % ret.type + ret.message)
return
# Assumes the user will always pass the number of seconds to pause the coroutine for.
yieldTime = ret[0]
timeSince = 0
PRs #110 and #112 introduce some issues.
What they solved
Before there was no way to force a lua coroutine or state to stop executing. Meaning scripts could easily crash the application or etc.
110 Added the method
pause_execution
to LuaCoroutine. Which would calllua_yield
in a hook it sets at the time the function is called. The hook would only run once.112 Added the methods
interrupt_execution
andkill
. Both of which would create a hook in the same manner as before.interrupt_execution
would raise an error one time. Kill would do the same, but never remove its hook.The issue
The intent was that the lua state would be executing on a separate thread when these methods were called. However accessing or modifying the lua state on multiple threads is not safe.
The fix
Instead of having predefined hooks and helper methods as before. This PR adds the ability for the user to create hooks from gdScript. It also adds the ability to yield the lua state from within these hooks. Using
yield_state
. Aswell as retrieving the current running corouitne from the parent LuaAPI object viaget_running_coroutine
.Example
CC @RadiantUwU