Skip to content

fix: prevent double-close in partsReader by advancing index after Close#60

Merged
sendya merged 2 commits into
mainfrom
fix/issue-57-double-close-part-reader
Jun 1, 2026
Merged

fix: prevent double-close in partsReader by advancing index after Close#60
sendya merged 2 commits into
mainfrom
fix/issue-57-double-close-part-reader

Conversation

@sendya
Copy link
Copy Markdown
Member

@sendya sendya commented Jun 1, 2026

Summary

  • 修复 partsReader.ReadClose() 返回错误时 r.index 未递增,导致后续 Close() 重复关闭已关闭的 reader
  • 修复 partsReader.WriteTo 中所有错误退出路径均未递增 r.index 的同源问题
  • 新增 3 个单元测试覆盖修复场景

根因

#57

Test plan

  • TestPartsReader_Read_CloseErrorAdvancesIndex — 验证 Read 中 Close 失败后索引前进
  • TestPartsReader_WriteTo_ErrorAdvancesIndex — 验证 WriteTo 中 io.Copy 错误后索引前进
  • TestPartsReader_WriteTo_AllSuccess — 验证正常 WriteTo 全路径
  • 全量 pkg/iobuf 测试通过

Closes #57

🤖 Generated with Claude Code

In partsReader.Read, when Close() returns an error after EOF, r.index was
not incremented — causing the same already-closed reader to be closed again
by the outer Close() method.

In partsReader.WriteTo, none of the three error-return paths incremented
r.index after closing the reader, leading to the same double-close bug.

Fix: increment r.index before returning in both error paths, so that a
closed reader is always marked as consumed regardless of Close/io.Copy
outcome.

Closes #57

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 1, 2026 02:32
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses a resource-lifecycle bug in pkg/iobuf’s composite partsReader where failures during per-part Close() could leave r.index unchanged, causing later Close() calls to double-close the same underlying reader (issue #57). It also adds unit tests covering the regression scenarios.

Changes:

  • Advance r.index when Read() encounters Close() errors after io.EOF, preventing subsequent double-close.
  • Advance r.index on WriteTo() error paths for the same double-close prevention.
  • Add 3 unit tests to cover the fixed scenarios.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
pkg/iobuf/part_reader.go Advances internal index on specific error paths in Read/WriteTo to avoid double-closing parts.
pkg/iobuf/part_reader_test.go Adds regression tests for index advancement on Close()/copy errors and successful WriteTo() behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pkg/iobuf/part_reader.go Outdated
Comment on lines +68 to +72
@@ -68,6 +69,7 @@ func (r *partsReader) WriteTo(w io.Writer) (n int64, err error) {
nn, err = io.Copy(w, reader)
n += nn
if err != nil {
r.index++
Comment on lines +29 to +47
// eofCloseErrReader returns data + io.EOF in a single Read, and returns the given error on Close.
type eofCloseErrReader struct {
data string
readOnce bool
closeErr error
closeCount *int
}

func (r *eofCloseErrReader) Read(p []byte) (int, error) {
if r.readOnce {
return 0, io.EOF
}
r.readOnce = true
n := copy(p, r.data)
if n == 0 {
return 0, io.EOF
}
return n, io.EOF
}
@sendya sendya merged commit 912df18 into main Jun 1, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

File close twice in part_reader

3 participants