Skip to content

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

@krisxia0506

Description

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

日志信息

相关截图 (如果有)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions