我目前正在用c ++包装一个lua类,到目前为止它还很顺利。但我想知道是否有某种方法可以打破另一个线程运行的lua脚本(可能在脚本中间)。因此,如果我在线程1上运行我的lua脚本,我可以从线程2中断它吗? lua_close(...)
会这样做吗?
感谢。
答案 0 :(得分:2)
然后必须有某种方法强制脚本停止?
不,没有。
Lua提供了完全一个线程安全保证:可以从两个不同的CPU线程自由调用两个单独的lua_State
(单独定义为lua_open
返回的不同对象) 。线程A可以调用lua_State
X,线程B可以调用lua_State
Y。
这是Lua给你的唯一保证。 Lua本质上是单线程的;它只提供这种保证,因为Lua的所有全局信息都包含在一个自包含的对象中:lua_State
。
Lua的规则要求任何时候只有一个线程与lua_State
对话。因此,Lua代码不可能执行,然后被外部C ++代码暂停或暂停。这需要打破规则:其他一些线程必须调用此线程的lua_State
上的函数。
如果要中止正在进行的脚本,则必须使用调试挂钩。这将大大降低脚本的性能(如果这对您很重要)。您还需要线程同步原语,以便线程B可以设置线程A将读取和暂停的标志。
至于你如何“中止”剧本,那......在最一般的情况下是不可能的。这就是原因。
lua_State
表示Lua执行线程。它有一个堆栈,指向要解释的指令,以及它当前正在执行的一些代码。要“中止”这不是Lua的概念。 Lua所拥有的是错误的概念。从Lua调用的C代码中调用lua_error
将导致该函数的longjmp
。这也将解开Lua线程,它将向最近处理错误的函数返回一个错误。
注意:如果在C ++代码中使用lua_error
,则需要将Lua编译为C ++(从而导致错误通过异常处理而不是setjmp
/ longjmp
)或你需要确保带有析构函数的每个对象在调用它时都不在堆栈中。不建议在C ++代码中调用longjmp
。
因此,如果您发出lua_pcall
来调用某个脚本,并在调试钩子中发出lua_error
,那么您将在lua_pcall
语句中收到错误消息。 Lua的堆栈将被解开,对象被破坏等等。这很好。
这在通用情况下不起作用的原因(除了我不知道Lua如何对调用lua_error
的调试挂钩做出反应这一事实非常简单:< em> Lua脚本也可以执行pcall
。错误将转到最近的pcall
语句,无论是在Lua还是在C中。
这个Lua脚本会混淆这种方法:
local function dostuff()
while true do end
end
while true do
pcall(dostuff)
end
因此发布lua_error
并不能保证您“中止脚本”。把它想象成抛出异常; 任何人都可以捕获它们,因此您无法确保它们只能在一个地方被捕获。
通常,您永远不应该想要中止正在执行的Lua脚本执行。这不是你想要做的事情。
答案 1 :(得分:1)
如果这是预期的事情并且Lua脚本的大部分时间都花在了Lua函数中(即,不是很长,阻塞C调用),你可以安装一个调试钩子来检查每个N指令的“break flag”和中止脚本。请参阅Programming in Lua的“调试库”部分。