Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 9576d0965442
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 54eace247ded
Choose a head ref
  • 4 commits
  • 5 files changed
  • 1 contributor

Commits on Nov 7, 2014

  1. Copy the full SHA
    a7878d0 View commit details
  2. Try to use an existing ChannelFD for native FDs, for close logic.

    If we create a new NativeDeviceChannel and ChannelFD, we lose the
    closed flag on the NIO channel that would raise an IOException.
    Instead, the lower levels of NIO close logic must swallow the
    EBADF we expect, and it never gets raised. This is likely a bad
    expectation on the part of NIO channel close logic, since the
    underlying fd *is* closed, but the channel does not know it.
    headius committed Nov 7, 2014
    Copy the full SHA
    76242f4 View commit details
  3. Copy the full SHA
    de133c9 View commit details
  4. Copy the full SHA
    54eace2 View commit details
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/RubyArgsFile.java
Original file line number Diff line number Diff line change
@@ -479,7 +479,7 @@ public static IRubyObject close(ThreadContext context, IRubyObject recv) {

data.next_argv(context);
if (isClosed(context, data.currentFile)) {
throw context.runtime.newIOError("closed stream");
throw context.runtime.newIOError(RubyIO.CLOSED_STREAM_MSG);
}

argf_close(context, data.currentFile);
40 changes: 19 additions & 21 deletions core/src/main/java/org/jruby/RubyIO.java
Original file line number Diff line number Diff line change
@@ -112,6 +112,7 @@ public class RubyIO extends RubyObject implements IOEncodable {
// We use a highly uncommon string to represent the paragraph delimiter (100% soln not worth it)
public static final ByteList PARAGRAPH_DELIMETER = ByteList.create("PARAGRPH_DELIM_MRK_ER");
public static final ByteList PARAGRAPH_SEPARATOR = ByteList.create("\n\n");
public static final String CLOSED_STREAM_MSG = "closed stream";

// This should only be called by this and RubyFile.
// It allows this object to be created without a IOHandler.
@@ -851,7 +852,12 @@ private IRubyObject initializeCommon(ThreadContext context, int fileno, IRubyObj
ChannelFD fd;

if (!FilenoUtil.isFake(fileno)) {
fd = new ChannelFD(new NativeDeviceChannel(fileno), runtime.getPosix(), runtime.getFilenoUtil());
// try using existing ChannelFD, then fall back on creating a new one
fd = runtime.getFilenoUtil().getWrapperFromFileno(fileno);

if (fd == null) {
fd = new ChannelFD(new NativeDeviceChannel(fileno), runtime.getPosix(), runtime.getFilenoUtil());
}
} else {
ChannelFD descriptor = runtime.getFilenoUtil().getWrapperFromFileno(fileno);

@@ -1103,21 +1109,7 @@ public static IRubyObject ensureYieldClose(ThreadContext context, IRubyObject po
try {
return block.yield(context, port);
} finally {
IRubyObject oldExc = runtime.getGlobalVariables().get("$!");
try {
if(!(port.respondsTo("closed?") && port.callMethod(context, "closed?").isTrue())) {
if(port.respondsTo("close")) {
port.getMetaClass().finvoke(context, port, "close", IRubyObject.NULL_ARRAY, Block.NULL_BLOCK);
}
}
} catch (RaiseException re) {
// MRI behavior: Ignore "closed stream"
if (re.getException().message.asJavaString().equals("closed stream")) {
runtime.getGlobalVariables().set("$!", oldExc);
} else {
throw re;
}
}
ioClose(runtime, port);
}
}
return port;
@@ -1934,12 +1926,18 @@ public IRubyObject close() {
// io_close
protected static IRubyObject ioClose(Ruby runtime, IRubyObject io) {
ThreadContext context = runtime.getCurrentContext();
IRubyObject closed = io.checkCallMethod(context, "closed?");
if (closed.isTrue()) return io;
try {
return io.callMethod(runtime.getCurrentContext(), "close");
return io.checkCallMethod(runtime.getCurrentContext(), "close");
} catch (RaiseException re) {
// ignore
context.setErrorInfo(context.nil);
return context.nil;
if (re.getMessage().contains(CLOSED_STREAM_MSG)) {
// ignore
context.setErrorInfo(context.nil);
return context.nil;
} else {
throw re;
}
}
}

@@ -3256,7 +3254,7 @@ public RubyIO to_io() {

@Override
public String toString() {
return "RubyIO(" + openFile.getMode() + ", " + openFile.fd().bestFileno() + ")";
return inspect().toString();
}

/* class methods for IO */
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/ext/stringio/StringIO.java
Original file line number Diff line number Diff line change
@@ -1278,7 +1278,7 @@ private void checkFinalized() {

private void checkOpen() {
if (closed()) {
throw getRuntime().newIOError("closed stream");
throw getRuntime().newIOError(RubyIO.CLOSED_STREAM_MSG);
}
}
}
10 changes: 5 additions & 5 deletions core/src/main/java/org/jruby/util/io/OpenFile.java
Original file line number Diff line number Diff line change
@@ -434,7 +434,7 @@ public boolean waitWritable(ThreadContext context, long timeout) {

if (posix.errno == null) return false;

if (fd == null) throw runtime.newIOError("closed stream");
if (fd == null) throw runtime.newIOError(RubyIO.CLOSED_STREAM_MSG);

switch (posix.errno) {
case EINTR:
@@ -461,7 +461,7 @@ public boolean waitReadable(ThreadContext context, long timeout) {

if (posix.errno == null) return false;

if (fd == null) throw runtime.newIOError("closed stream");
if (fd == null) throw runtime.newIOError(RubyIO.CLOSED_STREAM_MSG);

switch (posix.errno) {
case EINTR:
@@ -665,7 +665,7 @@ public void checkWritable(ThreadContext context) {

public void checkClosed() {
if (fd == null) {
throw runtime.newIOError("closed stream");
throw runtime.newIOError(RubyIO.CLOSED_STREAM_MSG);
}
}

@@ -1369,7 +1369,7 @@ public static int readInternal(ThreadContext context, OpenFile fptr, ChannelFD f
*/
boolean waitReadable(ThreadContext context, ChannelFD fd) {
if (fd == null) {
throw context.runtime.newIOError("closed stream");
throw context.runtime.newIOError(RubyIO.CLOSED_STREAM_MSG);
}

boolean locked = lock();
@@ -2280,7 +2280,7 @@ IRubyObject finishWriteconv(ThreadContext context, boolean noalloc) {
}
if (waitWritable(context)) {
if (fd == null)
return noalloc ? runtime.getTrue() : runtime.newIOError("closed stream").getException();
return noalloc ? runtime.getTrue() : runtime.newIOError(RubyIO.CLOSED_STREAM_MSG).getException();
continue retry;
}
break retry;
2 changes: 2 additions & 0 deletions test/mri/excludes/TestParse.rb
Original file line number Diff line number Diff line change
@@ -5,6 +5,8 @@
exclude :test_here_document, "needs investigation"
exclude :test_invalid_char, "needs investigation"
exclude :test_method_block_location, "needs investigation"
exclude :test_named_capture_conflict, "missing warning in parser (#2147)"
exclude :test_question, "needs investigation"
exclude :test_unused_variable, "missing warning in parser (#2147)"
exclude :test_void_expr_stmts_value, "1; next; 2 is figured via compile.c. IR can do equivalent for 9k. Not a huge issue for 1.7.x barring real issue"
exclude :test_xstring, "needs investigation"