Skip to content

Fix 100% CPU utilization when write closed#72

Merged
djc merged 2 commits into
rustls:mainfrom
ArniDagur:fix-write-after-close-error
Jul 17, 2026
Merged

Fix 100% CPU utilization when write closed#72
djc merged 2 commits into
rustls:mainfrom
ArniDagur:fix-write-after-close-error

Conversation

@ArniDagur

Copy link
Copy Markdown
Contributor

This fixes a bug we saw in production. There's a nasty interaction between h2 and the ktls crate. Namely:

  1. When the write-side of the connection is closed, the ktls crate returns Ok(0) instead of an error.
  2. h2 retries Ok(0) writes, instead of treating them as errors.

This led to busy looping, and 100% CPU utilization. I'm fixing this in both the h2 and ktls crates. The h2 variant of the fix is here: hyperium/h2#921.

The workspace conversion moved the crate into ktls/ but left tests/ at
the workspace root. The root is a virtual manifest, which owns no test
targets, so cargo has not discovered or run the integration suite since:
'cargo test --workspace' builds only the two unit-test binaries.

Move the directory into the ktls package, whose dev-dependencies it
already uses.
Once write_closed is set — the peer sent close_notify or a fatal alert,
or we shut the stream down — poll_write returned Ready(Ok(0)) forever.
Ok(0) is a poor fit here: callers that retry short writes cannot make
progress and spin at 100% CPU. We hit exactly that in production
through h2, whose frame-write loop re-polls until its buffer drains.

Return BrokenPipe instead, matching what writing to the raw socket
after shutdown would produce (EPIPE).

The existing write-after-shutdown assertions passed only because
write_all's zero-write fallback produced the error; assert on a bare
write and the error kind so the stream's own behavior is pinned, and
cover the peer-initiated close path on both the client and server
sides.

@djc djc left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I guess this makes sense?

ktls hasn't had much maintenance recently but this looks simple enough that it might make sense to merge and release.

@ArniDagur

Copy link
Copy Markdown
Contributor Author

ktls hasn't had much maintenance recently but this looks simple enough that it might make sense to merge and release

Yes, I think it's an important bug to address, so a good idea to merge/release. I setup a reproducer, and verified that this PR fixes the issue.

@djc
djc added this pull request to the merge queue Jul 17, 2026
Merged via the queue into rustls:main with commit d9d1381 Jul 17, 2026
2 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.

3 participants