【发布时间】:2016-07-12 10:54:49
【问题描述】:
我正在使用带有一些 Lua 绑定的 C++ 的多进程环境中工作,使用 Lua 函数来管理进程的某些方面,其中有一个共享的 Lua 上下文。
我使用的一般形式是挂钩某些事件,触发 Lua 函数,这些函数依次到达 C++ 代码。
我将两个与进程相关的参数压入栈中,然后发出
lua_call(L, 2, 0);
问题是某些特定的lua_call 达到了终止功能(预期行为),但是由于lua_call 没有返回,因此堆栈没有被释放。在大约 200 次这样的调用之后,由于 C 堆栈溢出,Lua 出现恐慌。
我已经在每个钩子上打印了 Lua 堆栈,我可以看到它在增长。我试过使用lua_pop(L, 2)(堆栈每次增长2),lua_settop(L, 0)在Lua使用参数并发出回调之后,就在终止进程之前,但无济于事。
我不能调用lua_close(L),因为这会破坏进程之间共享的上下文,并会导致其他进程访问 NULL 上下文。
【问题讨论】:
-
我认为最简单的解决方案是不在进程之间共享您的 Lua 上下文。 (实际上,我很惊讶它有效)
-
你需要使用某种锁,如果你同时通过一个 lua VM 运行两个线程,那么你会得到未定义的行为。
-
为什么 lua 调用不返回?如果这样做,您将泄漏堆栈条目,这与规范一致。当你用一些参数调用“lua_call”时,函数调用下面的参数将受到lua的保护,它会虚拟地移动堆栈帧以支持调用。 “原始”堆栈仅在您从函数返回时才可访问。您最终必须从通话中返回,否则这些条目将永远泄露 AFAIK。
-
@ChrisBeck:感谢您富有洞察力的评论!据我了解,在任何给定点,即使我可以查看任何堆栈帧,我也只能释放当前的堆栈帧。调用不返回的原因是因为调用的进程已因调用而被终止(同样,这是所需的行为)。我可以尝试的另一个选择是在调用以某种方式返回后安排进程终止。
-
@vladimird:您可以为每个进程使用单独的 Lua 线程。它们有独立的堆栈,当您不再需要它们时会进行垃圾回收。