test(triple): add concurrent send/close guards for duplexHTTPCall#3462
Merged
AlexStocks merged 1 commit intoJun 30, 2026
Merged
Conversation
Investigate whether connect-go v1.19.2's fix for the concurrent Send + CloseAndReceive nil-pointer dereference (connectrpc/connect-go#919) applies to Dubbo-go's forked Triple runtime. duplexHTTPCall is not affected: newDuplexHTTPCall allocates the request-body io.Pipe at construction and never reassigns requestBodyWriter, so it is always non-nil and concurrent Write/CloseWrite are safe in any order. The upstream race, where the pipe was created lazily on the first Send and a racing CloseWrite could leave it nil, is structurally impossible here, so no synchronization change is ported. - add TestDuplexHTTPCallConcurrentWriteAndCloseWrite and TestDuplexHTTPCallConcurrentWriteCloseRace as regression guards (run under -race) that pin the construction-time pipe invariant - document the invariant on requestBodyWriter to keep the allocation out of a lazy/first-send path Ref: apache#3458
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #3462 +/- ##
===========================================
+ Coverage 53.57% 53.90% +0.33%
===========================================
Files 460 461 +1
Lines 35182 35478 +296
===========================================
+ Hits 18847 19125 +278
+ Misses 14857 14848 -9
- Partials 1478 1505 +27 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
AlexStocks
reviewed
Jun 30, 2026
AlexStocks
left a comment
Contributor
There was a problem hiding this comment.
Review Summary
结论: ✅ 可 Merge
变更范围很小且精准:仅在 duplexHTTPCall 结构体上补充了 requestBodyWriter 构建时赋值不可变的注释不变量,并新增两个并发 guard test 作为回归保护。
核心判断:
newDuplexHTTPCall中io.Pipe()在构造时一次性分配,requestBodyWriter永不被重新赋值 — 从代码结构上杜绝了 connect-go#919 的 nil-pointer dereference 场景。d.response的写入发生在makeRequest()中close(d.responseReady)之前,所有读取方通过BlockUntilResponseReady()等待 channel 关闭后才访问 — channel close 提供了 Go memory model 的 happens-before 保证,无数据竞争。- 两个测试明确定位为 guard(非 reproducer),在正确代码上永远通过;但如果 pipe 创建被移到 lazy path,
assert.NotNil会立即失败 — 回归保护设计合理。 - 测试在
-race下运行可有效检测潜在 data race。
仅有一个 P2 建议,见 inline comment。
| @@ -0,0 +1,184 @@ | |||
| // Copyright 2021-2023 Buf Technologies, Inc. | |||
Contributor
There was a problem hiding this comment.
[P2] 新文件的 copyright 年份为 2021-2023,建议更新为 2021-2025(或至少 2025)。仓库内部分旧文件沿用旧年份可以理解,但新增文件建议使用当前年份。
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Description
Investigate whether connect-go v1.19.2's fix for the concurrent
Send+CloseAndReceivenil-pointer dereference (connectrpc/connect-go#919) applies toDubbo-go's forked Triple runtime under
protocol/triple/triple_protocol.Conclusion:
duplexHTTPCallis not affected.newDuplexHTTPCallallocatesthe request-body
io.Pipeat construction and never reassignsrequestBodyWriter, so it is always non-nil and concurrentWrite/CloseWriteare safe in any order. The upstream race — where the pipe was created lazily on
the first
Sendand a racingCloseWritecould leave it nil — is structurallyimpossible here, so no synchronization change is ported.
What this PR does:
TestDuplexHTTPCallConcurrentWriteAndCloseWriteandTestDuplexHTTPCallConcurrentWriteCloseRaceas regression guards (pass undergo test -race) that pin the construction-time pipe invariantrequestBodyWriterto keep the allocation out of alazy/first-send path
This is intentionally not a broad connect-go upgrade; it only checks and guards
the runtime safety property called out in the issue.
Fixes #3458
Checklist
develop