coai icon indicating copy to clipboard operation
coai copied to clipboard

CollectQuota 在 goroutine 中使用被复用的 *gin.Context 导致 utils.GetDBFromContext 报错 / panic

Open krisxia0506 opened this issue 2 months ago • 1 comments

  • [x] 我已确认目前没有类似 issue
  • [x] 我已确认我已升级到最新版本
  • [x] 我已完整浏览项目 README 和项目文档并未找到解决方案
  • [x] 我理解并愿意跟进此 issue,协助测试和提供反馈
  • [x] 我将以礼貌和尊重的态度提问,不得使用不文明用语 (包括在此发布评论的所有人同样适用, 不遵守的人将被 block)
  • [x] 我理解并认可上述内容,并理解项目维护者精力有限,不遵循规则的 issue 可能会被无视或直接关闭

问题描述

在 manager/chat_completions.go(约第 249 行)中,代码在请求处理过程中启动异步逻辑(goroutine)并将原始 *gin.Context 传入 CollectQuota。由于 gin.Context 会被放回 sync.Pool 并在后续请求中复用,如果原请求的 SSE/连接被关闭并且 context 被回收,而 goroutine 仍在运行,则后续请求可能重置该 context,导致 CollectQuota 中调用 utils.GetDBFromContext(c) 报错或引发竞态/panic。

复现步骤

  1. 在开启 SSE 的请求中触发会在后台 goroutine 中调用 CollectQuota 的逻辑(见 manager/chat_completions.go)。
  2. 在 goroutine 执行尚未完成时主动断开客户端连接(SSE 断开),使 gin.Context 被取消并回收到 pool。
  3. 随后发起另一个请求,使 pool 复用并重置该 *gin.Context。
  4. 正在运行的 goroutine 继续使用被复用/已重置的 *gin.Context,调用 utils.GetDBFromContext(c) 时可能读取到已重置的数据或触发 panic。

预期结果

后台/异步任务不应直接使用可能被复用或已被取消的 *gin.Context。应在启动 goroutine 之前提取所需依赖并传入,或使用 c.Copy()(注意 cCopy 的 Request.Context() 仍会被取消),或将后台任务改为使用独立的服务级 context。

日志信息

相关截图 (如果有)

krisxia0506 avatar Nov 14 '25 03:11 krisxia0506

Bot detected the issue body's language is not English, translate it automatically.


Title: CollectQuota uses the reused *gin.Context in goroutine, causing utils.GetDBFromContext to report an error/panic

  • [x] I have confirmed that there is currently no similar issue
  • [x] I have confirmed that I have upgraded to the latest version
  • [x] I have fully browsed the project README and project documentation and did not find a solution
  • [x] I understand and am willing to follow up on this issue, assist in testing and provide feedback
  • [x] I will ask questions in a polite and respectful manner and shall not use uncivilized language (the same applies to everyone who posts comments here, those who do not comply will be blocked)
  • [x] I understand and agree with the above content, and understand that project maintainers have limited energy. Issues that do not follow the rules may be ignored or closed directly

Problem description

In manager/chat_completions.go (around line 249), the code starts asynchronous logic (goroutine) during request processing and passes the original *gin.Context into CollectQuota. Since gin.Context will be put back into sync.Pool and reused in subsequent requests, if the SSE/connection of the original request is closed and the context is recycled while the goroutine is still running, subsequent requests may reset the context, causing an error or race/panic when calling utils.GetDBFromContext(c) in CollectQuota.

Steps to reproduce

Expected results

Log information

Relevant screenshots (if any)

Issues-translate-bot avatar Nov 14 '25 03:11 Issues-translate-bot