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: cf522e477761
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 9319c37ea9e5
Choose a head ref
  • 2 commits
  • 2 files changed
  • 1 contributor

Commits on Feb 23, 2015

  1. Always try to unwrap stdio streams.

    In order to have stdio streams report their actual file descriptor
    (usually 0, 1, 2, but possibly different on Windows), we need to
    always try to unwrap the FilterInput/OutputStream that wraps them
    on OpenJDK class-library-based JDKs. We do not want to do this
    for all processes, since as patched previously some JVMs attempt
    to drain subprocess streams. This is not necessary for stdio
    streams (as far as we know) so this commit adds a direct unwrap
    path we can use when setting up the globals.
    
    Fixes #2598
    headius committed Feb 23, 2015
    Copy the full SHA
    2e56c51 View commit details
  2. Copy the full SHA
    9319c37 View commit details
Showing with 50 additions and 16 deletions.
  1. +4 −3 core/src/main/java/org/jruby/RubyGlobal.java
  2. +46 −13 core/src/main/java/org/jruby/util/ShellLauncher.java
7 changes: 4 additions & 3 deletions core/src/main/java/org/jruby/RubyGlobal.java
Original file line number Diff line number Diff line change
@@ -56,6 +56,7 @@
import org.jruby.util.KCode;
import org.jruby.util.OSEnvironment;
import org.jruby.util.RegexpOptions;
import org.jruby.util.ShellLauncher;
import org.jruby.util.cli.OutputStrings;
import org.jruby.util.io.BadDescriptorException;
import org.jruby.util.io.OpenFile;
@@ -191,11 +192,11 @@ public static void createGlobals(ThreadContext context, Ruby runtime) {
runtime.defineVariable(new BacktraceGlobalVariable(runtime, "$@"), THREAD);

IRubyObject stdin = RubyIO.prepStdio(
runtime, runtime.getIn(), prepareStdioChannel(runtime, STDIO.IN, runtime.getIn()), OpenFile.READABLE, runtime.getIO(), "<STDIN>");
runtime, runtime.getIn(), prepareStdioChannel(runtime, STDIO.IN, ShellLauncher.unwrapFilterInputStream(runtime.getIn())), OpenFile.READABLE, runtime.getIO(), "<STDIN>");
IRubyObject stdout = RubyIO.prepStdio(
runtime, runtime.getOut(), prepareStdioChannel(runtime, STDIO.OUT, runtime.getOut()), OpenFile.WRITABLE, runtime.getIO(), "<STDOUT>");
runtime, runtime.getOut(), prepareStdioChannel(runtime, STDIO.OUT, ShellLauncher.unwrapFilterOutputStream(runtime.getOut())), OpenFile.WRITABLE, runtime.getIO(), "<STDOUT>");
IRubyObject stderr = RubyIO.prepStdio(
runtime, runtime.getErr(), prepareStdioChannel(runtime, STDIO.ERR, runtime.getErr()), OpenFile.WRITABLE | OpenFile.SYNC, runtime.getIO(), "<STDERR>");
runtime, runtime.getErr(), prepareStdioChannel(runtime, STDIO.ERR, ShellLauncher.unwrapFilterOutputStream(runtime.getErr())), OpenFile.WRITABLE | OpenFile.SYNC, runtime.getIO(), "<STDERR>");

runtime.defineVariable(new InputGlobalVariable(runtime, "$stdin", stdin), GLOBAL);
runtime.defineVariable(new OutputGlobalVariable(runtime, "$stdout", stdout), GLOBAL);
59 changes: 46 additions & 13 deletions core/src/main/java/org/jruby/util/ShellLauncher.java
Original file line number Diff line number Diff line change
@@ -826,16 +826,8 @@ private static Process popenShared(Ruby runtime, IRubyObject[] strings, Map env,
*/
public static OutputStream unwrapBufferedStream(OutputStream filteredStream) {
if (RubyInstanceConfig.NO_UNWRAP_PROCESS_STREAMS) return filteredStream;
while (filteredStream instanceof FilterOutputStream) {
try {
filteredStream = (OutputStream)
FieldAccess.getProtectedFieldValue(FilterOutputStream.class,
"out", filteredStream);
} catch (Exception e) {
break; // break out if we've dug as deep as we can
}
}
return filteredStream;

return unwrapFilterOutputStream(filteredStream);
}

/**
@@ -855,12 +847,53 @@ public static InputStream unwrapBufferedStream(InputStream filteredStream) {
if (filteredStream.getClass().getName().indexOf("ProcessPipeInputStream") != 1) {
return filteredStream;
}


return unwrapFilterInputStream((FilterInputStream)filteredStream);
}

/**
* Unwrap the given stream to its first non-FilterOutputStream. If the stream is not
* a FilterOutputStream it is returned immediately.
*
* Note that this version is used when you are absolutely sure you want to unwrap;
* the unwrapBufferedStream version will perform checks for certain types of
* process-related streams that should not be unwrapped (Java 7+ Process, e.g.).
*
* @param filteredStream a stream to be unwrapped, if it is a FilterOutputStream
* @return the deeped non-FilterOutputStream stream, or filterOutputStream if it is
* not a FilterOutputStream to begin with.
*/
public static OutputStream unwrapFilterOutputStream(OutputStream filteredStream) {
while (filteredStream instanceof FilterOutputStream) {
try {
filteredStream = (OutputStream)
FieldAccess.getProtectedFieldValue(FilterOutputStream.class,
"in", filteredStream);
} catch (Exception e) {
break; // break out if we've dug as deep as we can
}
}
return filteredStream;
}

/**
* Unwrap the given stream to its first non-FilterInputStream. If the stream is not
* a FilterInputStream it is returned immediately.
*
* Note that this version is used when you are absolutely sure you want to unwrap;
* the unwrapBufferedStream version will perform checks for certain types of
* process-related streams that should not be unwrapped (Java 7+ Process, e.g.).
*
* @param filteredStream a stream to be unwrapped, if it is a FilterInputStream
* @return the deeped non-FilterInputStream stream, or filterInputStream if it is
* not a FilterInputStream to begin with.
*/
public static InputStream unwrapFilterInputStream(InputStream filteredStream) {
while (filteredStream instanceof FilterInputStream) {
try {
filteredStream = (InputStream)
FieldAccess.getProtectedFieldValue(FilterInputStream.class,
"in", filteredStream);
FieldAccess.getProtectedFieldValue(FilterInputStream.class,
"in", filteredStream);
} catch (Exception e) {
break; // break out if we've dug as deep as we can
}