# HG changeset patch # User jlaskey # Date 1370439170 10800 # Node ID 35bba63990b7f7b4eb319781201baa3bab5dd7c9 # Parent 60bc560df392ccfd0eef1165b3bc72d85ba8a611 8015911: $EXEC does not handle large outputs Reviewed-by: sundar, attila Contributed-by: james.laskey@oracle.com diff -r 60bc560df392 -r 35bba63990b7 src/jdk/nashorn/internal/runtime/ScriptingFunctions.java --- a/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java Wed Jun 05 12:44:24 2013 +0200 +++ b/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java Wed Jun 05 10:32:50 2013 -0300 @@ -32,9 +32,8 @@ import java.io.BufferedReader; import java.io.File; import java.io.IOException; -import java.io.InputStream; import java.io.InputStreamReader; -import java.io.OutputStream; +import java.io.OutputStreamWriter; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.util.Map; @@ -165,36 +164,61 @@ // Start the process. final Process process = processBuilder.start(); + final IOException exception[] = new IOException[2]; + + // Collect output. + final StringBuilder outBuffer = new StringBuilder(); + Thread outThread = new Thread(new Runnable() { + @Override + public void run() { + char buffer[] = new char[1024]; + try (final InputStreamReader inputStream = new InputStreamReader(process.getInputStream())) { + for (int length; (length = inputStream.read(buffer, 0, buffer.length)) != -1; ) { + outBuffer.append(buffer, 0, length); + } + } catch (IOException ex) { + exception[0] = ex; + } + } + }, "$EXEC output"); + + // Collect errors. + final StringBuilder errBuffer = new StringBuilder(); + Thread errThread = new Thread(new Runnable() { + @Override + public void run() { + char buffer[] = new char[1024]; + try (final InputStreamReader inputStream = new InputStreamReader(process.getErrorStream())) { + for (int length; (length = inputStream.read(buffer, 0, buffer.length)) != -1; ) { + outBuffer.append(buffer, 0, length); + } + } catch (IOException ex) { + exception[1] = ex; + } + } + }, "$EXEC error"); + + // Start gathering output. + outThread.start(); + errThread.start(); // If input is present, pass on to process. - try (OutputStream outputStream = process.getOutputStream()) { + try (OutputStreamWriter outputStream = new OutputStreamWriter(process.getOutputStream())) { if (input != UNDEFINED) { - outputStream.write(JSType.toString(input).getBytes()); + String in = JSType.toString(input); + outputStream.write(in, 0, in.length()); } + } catch (IOException ex) { + // Process was not expecting input. May be normal state of affairs. } // Wait for the process to complete. final int exit = process.waitFor(); + outThread.join(); + errThread.join(); - // Collect output. - String out; - try (InputStream inputStream = process.getInputStream()) { - final StringBuilder outBuffer = new StringBuilder(); - for (int ch; (ch = inputStream.read()) != -1; ) { - outBuffer.append((char)ch); - } - out = outBuffer.toString(); - } - - // Collect errors. - String err; - try (InputStream errorStream = process.getErrorStream()) { - final StringBuilder errBuffer = new StringBuilder(); - for (int ch; (ch = errorStream.read()) != -1; ) { - errBuffer.append((char)ch); - } - err = errBuffer.toString(); - } + final String out = outBuffer.toString(); + final String err = errBuffer.toString(); // Set globals for secondary results. final boolean isStrict = global.isStrictContext(); @@ -202,6 +226,13 @@ global.set(ERR_NAME, err, isStrict); global.set(EXIT_NAME, exit, isStrict); + // Propagate exception if present. + for (int i = 0; i < exception.length; i++) { + if (exception[i] != null) { + throw exception[i]; + } + } + // Return the result from stdout. return out; }