Co::getBackTrace() 仅在当前协程内有效且不包含函数参数和局部变量;须在协程上下文中调用,不支持 debug_backtrace() 的 flags,异常处理应于 throw 前快照堆栈并配合协程 ID 记录。
Co::getBackTrace() 不是 debug_backtrace() 的协程安全替代品,它只在当前协程内有效,且默认不包含函数参数和局部变量 —— 这是绝大多数人踩坑的起点。
Co::getBackTrace() 返回空或不完整常见现象:在 go 启动的协程外调用,或在 defer / finally 中误以为能捕获到“抛出点”堆栈,结果返回空数组或只有顶层框架调用。
SwooleCoroutine::getCurrent() !== null 为真时才可用DEBUG_BACKTRACE_PROVIDE_OBJECT 和 DEBUG_BACKTRACE_IGNORE_ARGS 等 flag,传入会被忽略co::sleep() 中断后恢复前被销毁),调用会返回空数组opcache.enable_cli=1,可能因优化导致部分帧丢失,建议开发期关闭不能依赖 try/catch 外层的 Co::getBackTrace(),因为异常抛出时协程上下文可能已切换;需在 throw 前主动快照。
__construct() 中立即调用:$this->coroutineTrace = Co::getBackTrace();
SwooleCoroutine::getUid() 记录协程 ID,避免日志混淆debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10) + 手动过滤非协程帧(检查 file 是否含 vendor/swoole/ 或 Runtime/)__toString() 或 __debugInfo() 中调用,可能引发递归或上下文丢失Co::getBackTrace() 和 debug_backtrace() 混用的风险两者返回结构相似但语义不同:Co::getBackTrace() 是纯协程调度器视角的调用链,不含 include/eval 帧;而 debug_backtrace() 是 Zend VM 视角,可能跨协程混杂。
"trace_source": "co" 或 "trace_source": "vm"
Co::getBackTrace() 开销约是 debug_backtrace() 的 1/3,但叠加使用会翻倍onReceive 回调中首次调用 Co::getBackTrace() 可能触发 segfault,建议升级至 4.8.13+真正难的不是拿到堆栈,而是判断哪一层该截断、哪些帧属于 Swoole 底层调度器、哪些是业务关键路径 —— 这需要结合 Co::getUid()、Co::stats() 和实际协程生命周期来交叉验证。