00bd63cfdf
线上 v1.2.158 销假必崩,前端显示「连接失败,请检查网络」,用户误判为网络问题。
根因(162 服务器日志实证):
SetBodyStreamWriter 的回调运行在 fasthttp 的独立写协程中,此时 *RequestCtx
已被归还复用。回调内调用 newXsgzSession(c.Context(), ...) 把该 ctx 交给
resty 的 SetContext,resty 内部走 context.WithDeadline → propagateCancel
→ parent.Done(),而 RequestCtx.Done() 直接解引用 ctx.s(server.go:2726):
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV] fasthttp.(*RequestCtx).Done server.go:2726
此时 s 已为 nil,触发 SIGSEGV。
panic 发生在协程里,fiber 的 recover 中间件捕获不到,直接杀死整个进程,
前端 XHR 连接被掐断 → 只剩「连接失败,请检查网络」这条误导性提示。
修复:
1. 新增 streamCtx():返回 context.WithTimeout(Background, 3min),
脱离请求生命周期,回调内一律使用它(销假与请假两条链路);
2. 两个回调都加 recover 兜底,即便再出现协程内 panic 也只返回
task_error 事件,不会拖垮进程。
回归测试:TestStreamCtxIsUsable 保证 ctx 具备 Done/deadline;
TestRequestCtxDonePanicsAfterReset 用零值 RequestCtx 固化崩溃机制,
解释为什么不能用 c.Context()。