Skip to content

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

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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions