Skip to content

fix: clear pending stream I/O tasks on cancellation#94

Merged
richard-ramos merged 3 commits into
mainfrom
pending
Jun 26, 2026
Merged

fix: clear pending stream I/O tasks on cancellation#94
richard-ramos merged 3 commits into
mainfrom
pending

Conversation

@richard-ramos

Copy link
Copy Markdown
Member

Summary

Cancelling a pending Stream.readOnce or Stream.write clears the registered stream task and disables the corresponding lsquic read/write interest. This prevents cancelled operations from leaving stale caller-owned buffers attached to future stream callbacks.

Risk Assessment

The change is localized to stream read/write cancellation cleanup. The main risk is around stream close/reset timing while a pending operation is being cleared.

@richard-ramos
richard-ramos requested a review from a team as a code owner June 18, 2026 19:24
@richard-ramos
richard-ramos requested review from Copilot, gmelodie and vladopajic and removed request for a team June 18, 2026 19:24

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 18, 2026 19:25

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Comment thread lsquic/stream.nim
Comment on lines +93 to +125
proc clearPendingRead(
stream: Stream, doneFut: Future[int].Raising([CancelledError, StreamError])
) {.raises: [].} =
let task = stream.toRead.valueOr:
return
if task.doneFut != doneFut:
return

stream.toRead = Opt.none(ReadTask)

if stream.closedByEngine or stream.quicStream.isNil:
return

if lsquic_stream_wantread(stream.quicStream, 0) == -1:
error "could not set stream wantread",
streamId = lsquic_stream_id(stream.quicStream)

proc clearPendingWrite(
stream: Stream, doneFut: Future[void].Raising([CancelledError, StreamError])
) {.raises: [].} =
let task = stream.toWrite.valueOr:
return
if task.doneFut != doneFut:
return

stream.toWrite = Opt.none(WriteTask)

if stream.closedByEngine or stream.quicStream.isNil:
return

if lsquic_stream_wantwrite(stream.quicStream, 0) == -1:
error "could not set stream wantwrite",
streamId = lsquic_stream_id(stream.quicStream)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Probably a nit but i feel like these two could be only one template

@richard-ramos
richard-ramos merged commit 1bb8df6 into main Jun 26, 2026
21 checks 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.

4 participants