获取协同程序的完整堆栈,包括在哪里恢复协同程序



一个简单的例子:

coroutine.resume(coroutine.create(function()
print(debug.traceback())
end))
print(debug.traceback())

输出:

stack traceback:
./v.lua:2: in function <./v.lua:1>
stack traceback:
./v.lua:4: in main chunk
[C]: in ?

这表明协程中的traceback不知道它是如何恢复的,所以xxx: in main chunk不会显示。

如何在协同游戏中获得完整的堆叠游戏?

好吧,我在这里找到了一个解决方法。

由于一个Lua虚拟机一次只有一个执行点(这就是为什么那里有一个完整的调用堆栈(,我们可以手动记录恢复信息。

在lua中,手动构建一个恢复堆栈跟踪。

local xresume = coroutine.resume
local xtrace = debug.traceback
-- magic here! Take care of main thread.
local mainthr = coroutine.running()      -- captureing is a must.
debug.traceback = function(athr)
if athr then return xtrace(athr) end  -- no interest in specified thread.
return xtrace(mainthr)
end
coroutine.resume = function(thr, ...)
-- another magic.
local uptrace = debug.traceback
debug.traceback = function(athr)
if athr then return xtrace(athr) end  -- no interest in specified thread.
return xtrace(thr)     -- trace the stack of thr.
.. 'n' .. uptrace() -- trace from thr's resume point.
end

local result = { xresume(thr, ...) }
debug.traceback = uptrace
return table.unpack(result)
end

其他提示:

  • 使用全局表存储线程也可以。但您仍然需要捕获主线程,以便可以在任何地方跟踪它。

  • 在C函数中编写代码可以防止回溯到挂接的coroutine.resumedebug.traceback本身,从而提供更清晰的输出。

  • 如果不调用debug.traceback,则不会对性能造成太大影响。

最新更新