Wed, 05 Jun 2013 10:32:50 -0300
8015911: $EXEC does not handle large outputs
Reviewed-by: sundar, attila
Contributed-by: james.laskey@oracle.com
src/jdk/nashorn/internal/runtime/ScriptingFunctions.java | file | annotate | diff | comparison | revisions |
1.1 --- a/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java Wed Jun 05 12:44:24 2013 +0200 1.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java Wed Jun 05 10:32:50 2013 -0300 1.3 @@ -32,9 +32,8 @@ 1.4 import java.io.BufferedReader; 1.5 import java.io.File; 1.6 import java.io.IOException; 1.7 -import java.io.InputStream; 1.8 import java.io.InputStreamReader; 1.9 -import java.io.OutputStream; 1.10 +import java.io.OutputStreamWriter; 1.11 import java.lang.invoke.MethodHandle; 1.12 import java.lang.invoke.MethodHandles; 1.13 import java.util.Map; 1.14 @@ -165,36 +164,61 @@ 1.15 1.16 // Start the process. 1.17 final Process process = processBuilder.start(); 1.18 + final IOException exception[] = new IOException[2]; 1.19 + 1.20 + // Collect output. 1.21 + final StringBuilder outBuffer = new StringBuilder(); 1.22 + Thread outThread = new Thread(new Runnable() { 1.23 + @Override 1.24 + public void run() { 1.25 + char buffer[] = new char[1024]; 1.26 + try (final InputStreamReader inputStream = new InputStreamReader(process.getInputStream())) { 1.27 + for (int length; (length = inputStream.read(buffer, 0, buffer.length)) != -1; ) { 1.28 + outBuffer.append(buffer, 0, length); 1.29 + } 1.30 + } catch (IOException ex) { 1.31 + exception[0] = ex; 1.32 + } 1.33 + } 1.34 + }, "$EXEC output"); 1.35 + 1.36 + // Collect errors. 1.37 + final StringBuilder errBuffer = new StringBuilder(); 1.38 + Thread errThread = new Thread(new Runnable() { 1.39 + @Override 1.40 + public void run() { 1.41 + char buffer[] = new char[1024]; 1.42 + try (final InputStreamReader inputStream = new InputStreamReader(process.getErrorStream())) { 1.43 + for (int length; (length = inputStream.read(buffer, 0, buffer.length)) != -1; ) { 1.44 + outBuffer.append(buffer, 0, length); 1.45 + } 1.46 + } catch (IOException ex) { 1.47 + exception[1] = ex; 1.48 + } 1.49 + } 1.50 + }, "$EXEC error"); 1.51 + 1.52 + // Start gathering output. 1.53 + outThread.start(); 1.54 + errThread.start(); 1.55 1.56 // If input is present, pass on to process. 1.57 - try (OutputStream outputStream = process.getOutputStream()) { 1.58 + try (OutputStreamWriter outputStream = new OutputStreamWriter(process.getOutputStream())) { 1.59 if (input != UNDEFINED) { 1.60 - outputStream.write(JSType.toString(input).getBytes()); 1.61 + String in = JSType.toString(input); 1.62 + outputStream.write(in, 0, in.length()); 1.63 } 1.64 + } catch (IOException ex) { 1.65 + // Process was not expecting input. May be normal state of affairs. 1.66 } 1.67 1.68 // Wait for the process to complete. 1.69 final int exit = process.waitFor(); 1.70 + outThread.join(); 1.71 + errThread.join(); 1.72 1.73 - // Collect output. 1.74 - String out; 1.75 - try (InputStream inputStream = process.getInputStream()) { 1.76 - final StringBuilder outBuffer = new StringBuilder(); 1.77 - for (int ch; (ch = inputStream.read()) != -1; ) { 1.78 - outBuffer.append((char)ch); 1.79 - } 1.80 - out = outBuffer.toString(); 1.81 - } 1.82 - 1.83 - // Collect errors. 1.84 - String err; 1.85 - try (InputStream errorStream = process.getErrorStream()) { 1.86 - final StringBuilder errBuffer = new StringBuilder(); 1.87 - for (int ch; (ch = errorStream.read()) != -1; ) { 1.88 - errBuffer.append((char)ch); 1.89 - } 1.90 - err = errBuffer.toString(); 1.91 - } 1.92 + final String out = outBuffer.toString(); 1.93 + final String err = errBuffer.toString(); 1.94 1.95 // Set globals for secondary results. 1.96 final boolean isStrict = global.isStrictContext(); 1.97 @@ -202,6 +226,13 @@ 1.98 global.set(ERR_NAME, err, isStrict); 1.99 global.set(EXIT_NAME, exit, isStrict); 1.100 1.101 + // Propagate exception if present. 1.102 + for (int i = 0; i < exception.length; i++) { 1.103 + if (exception[i] != null) { 1.104 + throw exception[i]; 1.105 + } 1.106 + } 1.107 + 1.108 // Return the result from stdout. 1.109 return out; 1.110 }