Skip to content

Commit

Permalink
Ensure copy_stream write sends all bytes read (#6348)
Browse files Browse the repository at this point in the history
On target streams that may do partial reads, the logic here fails
to write all content read from the source stream. The return value
of Channel.write is never checked, but the total bytes written is
incremented, resulting in silently losing data.

The patch loops until all bytes have been written to the output
channel after each read.

CRuby does similar logic. We may need to add additional blocking
write or thread event checks here, in case the target stream
blocks during the write loop, but that will require the different
`transfer` paths to be expanded to support nonblocking IO
channels.

Fixes #6078

Back-port of bc9a5ac
Co-authored-by: Charles Oliver Nutter <headius@headius.com>
  • Loading branch information
kares committed Jul 30, 2020
1 parent d9c534c commit 36084b5
Showing 1 changed file with 5 additions and 1 deletion.
6 changes: 5 additions & 1 deletion core/src/main/java/org/jruby/RubyIO.java
Original file line number Diff line number Diff line change
Expand Up @@ -4451,8 +4451,12 @@ private static long transfer(ThreadContext context, ReadableByteChannel from, Wr

if (n == -1) break;

// write buffer fully and then clear
flipBuffer(buffer);
to.write(buffer);
long w = 0;
while (w < n) {
w += to.write(buffer);
}
clearBuffer(buffer);

transferred += n;
Expand Down

0 comments on commit 36084b5

Please sign in to comment.