Skip to content

[nats] 订阅 handler 的 panic 直接炸掉整个进程——SubscribeJSON 连坏 JSON 都兜了底,却把 handler panic 漏进 nats.go 内部 goroutine,一条畸形消息杀掉全部订阅 #145

Closed

Description

@zy84338719

现象

nats/client.go:275/300/314/383 的 Subscribe / SubscribeJSON / QueueSubscribeJSON / Reply 全部把用户 handler 原样透传给上游 SDK:

// client.go:300
func SubscribeJSON[T any](c *Client, subject string, handler func(ctx context.Context, msg *T)) (*nats.Subscription, error) {
	return c.Subscribe(subject, func(m *nats.Msg) { ... handler(extractTraceCtx(m), &payload) })
}

而 nats.go v1.55.0 的异步派发循环直接调用、无任何 recover(nats.go@v1.55.0/nats.go:3861:mcb(m),全文件的 recover 只用于 closeStatusListener)。同仓明文约定 AGENTS.md:31「禁止裸 go func:用 github.com/oekit/concurrency/async 的 GoSafe 系列(panic 被 recover)」,且 wsutil/outbox.go:108 写着「写协程 panic 只许死这条连接,不许死整个进程」——唯独接收外部不可信载荷的订阅 handler 没有这层隔离。

探针复现(/tmp/pbprobe,内嵌 nats-server,handler 对 "boom" panic):

[natspanic] benign message handled
panic: handler panic (simulated)
goroutine 24 [running]:
main.natspanic.func1(...)        /tmp/pbprobe/main.go:55
github.com/oekit/network/nats.SubscribeJSON[...].func1()  /Users/zhangyi/oekit/network/nats/client.go:307
github.com/nats-io/nats.go.(*Conn).waitForMsgs(...)       nats.go@v1.55.0/nats.go:3861
exit status 2

失败场景推演

一条业务消息 JSON 反序列化成功但语义残缺(可选字段为 nil、map 查不到 key)→ handler nil 解引用 panic → 穿透 waitForMsgs 无 recover → 进程退出。后果:该进程上所有订阅、所有连接、所有在途请求一并消灭;core NATS 无持久化,这条消息永久丢失、服务端零记录。SubscribeJSON 对坏 JSON 特意做了「log 后跳过」的健壮性(client.go:303-306),唯独更常见的 handler 内 panic 没兜。

为什么测试没抓到

nats 包的 panic 相关测试全部是 nil ctx 兜底回归(nats_issue_fix_test.go:33 等,#79/#101 修复面),没有任何 handler panic 用例;panic 发生在上游 SDK goroutine,-race 也不检出。

建议修复方向

Subscribe/SubscribeJSON/QueueSubscribe/QueueSubscribeJSON/Reply 的 handler 调用点包 async.GoSafeLabeled(panic 收编为 Error 日志 + 消息丢弃留痕,与 outbox 的「只死这条连接」同口径);至少在 godoc 显著位置明示「handler panic = 进程崩溃」。


置信度:高(探针复现:进程 exit status 2 + 堆栈直指 waitForMsgs 无 recover;基线 = network 9f3d2c3)

与既有 issue 的差异:33 条已有 issue 中 #79/#100/#101 是「API 入口 nil ctx panic」,无任何 handler panic 隔离议题;与 #54(flaky 测试)无关。

Activity

  1. added 2 commits that reference this issue on Nov 10, 2026
  2. zy84338719 commented on Nov 10, 2026

    @zy84338719
    ContributorAuthor

    已在 v0.9.2 修复并发布 ✅

    变更内容

    本条修复(在 v0.9.2 的版本节里定位到):

    该版本 `v0.9.2` 的其余变更

    关联问题单:#145。

    关联问题单:#146。

    关联问题单:#147。

    Release: https://github.com/oekit/network/releases/tag/v0.9.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions