Skip to content

Fix SSL write data loss and flush-before-read on non-blocking writes#347

Open
jsvd wants to merge 1 commit intojruby:masterfrom
jsvd:fix-ssl-write-flush-before-read
Open

Fix SSL write data loss and flush-before-read on non-blocking writes#347
jsvd wants to merge 1 commit intojruby:masterfrom
jsvd:fix-ssl-write-flush-before-read

Conversation

@jsvd
Copy link

@jsvd jsvd commented Mar 16, 2026

Two bugs in SSLSocket cause data loss when using write_nonblock followed by sysread (the pattern used by net/http for POST requests):

  1. write() unconditionally calls netWriteData.clear() after a non-blocking flushData(), discarding any encrypted bytes that weren't yet sent to the socket. Fix: use compact() which preserves unsent bytes.

  2. sysreadImpl() never flushes pending netWriteData before reading. After the last write_nonblock, encrypted data can remain in the buffer and never reach the server. Fix: flush netWriteData at the start of sysreadImpl().

This was observed as EOFError during gem push on JRuby 10 with large gem files: the server never received the complete POST body and sent close_notify instead of an HTTP response.

fixes #242

Two bugs in SSLSocket cause data loss when using write_nonblock followed
by sysread (the pattern used by net/http for POST requests):

1. write() unconditionally calls netWriteData.clear() after a non-blocking
   flushData(), discarding any encrypted bytes that weren't yet sent to the
   socket. Fix: use compact() which preserves unsent bytes.

2. sysreadImpl() never flushes pending netWriteData before reading. After
   the last write_nonblock, encrypted data can remain in the buffer and
   never reach the server. Fix: flush netWriteData at the start of
   sysreadImpl().

This was observed as EOFError during `gem push` on JRuby 10 with large
gem files: the server never received the complete POST body and sent
close_notify instead of an HTTP response.
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.

gem push fails with Broken Pipe IOError

1 participant