从另一个线程中断c++中的lua脚本

Break a lua script in c++ from another thread?

本文关键字:中的 lua 脚本 c++ 中断 另一个 线程      更新时间:2023-10-16

我目前正在用c++包装一个lua类,到目前为止进展顺利。但我想知道是否有什么方法可以阻止lua脚本为另一个线程运行(可能是在脚本的中间)。所以,如果我在线程1上运行lua脚本,我可以从线程2中断它吗?lua_close(...)会这么做吗?

谢谢。

如果这是预期的情况,并且Lua脚本的大部分时间都花在Lua函数中(即不长,阻塞C调用),则可以安装一个调试挂钩,每隔N条指令检查一次"break flag"并中止脚本。请参阅Lua中编程的"调试库"部分。

那么一定有什么方法可以强制脚本停止?

不,没有。

Lua提供了一个线程安全保证:两个独立的lua_States(单独定义为lua_open返回的不同对象)可以从两个不同的CPU线程中自由调用。线程A可以调用lua_State X,线程B可以调用lua_State Y。

这是Lua给您的唯一保证。Lua本质上是单螺纹的;它只提供这种保证,因为Lua的所有全局信息都包含在一个自包含的对象CCD_。

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的调试挂钩会有什么反应):Lua脚本也可以执行pcall。错误将转到最近的pcall语句,无论它是在Lua中还是在C.中

这个Lua脚本将混淆这种方法:

local function dostuff()
  while true do end
end
while true do
  pcall(dostuff)
end

因此,发出lua_error并不能保证你会"中止脚本"任何人都可以抓住它们,所以你不能确保它们只在一个地方被抓住。

通常,您不应该希望中止正在执行的Lua脚本。这不是你应该做的事情。