Skip to content

Commit

Permalink
Fixes #3745. IO#block_nonwrite causes CCE on Windows.
Browse files Browse the repository at this point in the history
I made a marker interface so that both ChannelStream and CRLFStream
wrapper can have a common type so they can call writenonblock.  I added
an error check to throw and IOException if CRLFStreamWrapper is wrapping
from stream type but I suspect it is an impossible path by this point in
our code.  Zero 1.7 risk fix since this was just dumping stack before.
enebo committed Mar 18, 2016
1 parent 4496cff commit 3eb8c5f
Showing 4 changed files with 22 additions and 3 deletions.
3 changes: 2 additions & 1 deletion core/src/main/java/org/jruby/RubyIO.java
Original file line number Diff line number Diff line change
@@ -43,6 +43,7 @@
import org.jruby.util.io.EncodingUtils;
import org.jruby.util.io.FileExistsException;
import org.jruby.util.io.ModeFlags;
import org.jruby.util.io.NonblockWritingStream;
import org.jruby.util.io.SelectBlob;
import jnr.constants.platform.Fcntl;
import java.io.EOFException;
@@ -1381,7 +1382,7 @@ public IRubyObject doWriteNonblock(ThreadContext context, IRubyObject obj, boole
runtime.getWarnings().warn(ID.SYSWRITE_BUFFERED_IO, "write_nonblock for buffered IO");
}

ChannelStream stream = (ChannelStream)myOpenFile.getWriteStream();
NonblockWritingStream stream = (NonblockWritingStream)myOpenFile.getWriteStream();

int written = stream.writenonblock(str.getByteList());
if (written == 0) {
8 changes: 7 additions & 1 deletion core/src/main/java/org/jruby/util/io/CRLFStreamWrapper.java
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@
* Wrapper around Stream that packs and unpacks LF <=> CRLF.
* @author nicksieger
*/
public class CRLFStreamWrapper implements Stream {
public class CRLFStreamWrapper implements Stream, NonblockWritingStream {
private final Stream stream;
private final boolean isWindows;
private boolean binmode = false;
@@ -128,6 +128,12 @@ public ByteList fread(int number) throws IOException, BadDescriptorException, EO
return bl;
}

public synchronized int writenonblock(ByteList buf) throws IOException, BadDescriptorException {
if (!(stream instanceof ChannelStream)) throw new IOException("write_nonblock from a stream which does not support it");

return ((ChannelStream) stream).writenonblock(convertLFToCRLF(buf));
}

public int fwrite(ByteList string) throws IOException, BadDescriptorException {
if (isWindows) return stream.fwrite(convertLFToCRLF(string));

2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/util/io/ChannelStream.java
Original file line number Diff line number Diff line change
@@ -60,7 +60,7 @@
/**
* This file implements a seekable IO file.
*/
public class ChannelStream implements Stream, Finalizable {
public class ChannelStream implements Stream, Finalizable, NonblockWritingStream {

private static final Logger LOG = LoggerFactory.getLogger("ChannelStream");

12 changes: 12 additions & 0 deletions core/src/main/java/org/jruby/util/io/NonblockWritingStream.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.jruby.util.io;

import java.io.IOException;
import org.jruby.util.ByteList;

/**
* Hacky marker interface for 1.9 support of CRLFStreamWrapper.
* So it and the natural stream ChannelStream can both call nonblockingwrite.
*/
public interface NonblockWritingStream {
public int writenonblock(ByteList buf) throws IOException, BadDescriptorException;
}

0 comments on commit 3eb8c5f

Please sign in to comment.