8015911: $EXEC does not handle large outputs

Wed, 05 Jun 2013 10:32:50 -0300

author
jlaskey
date
Wed, 05 Jun 2013 10:32:50 -0300
changeset 327
35bba63990b7
parent 326
60bc560df392
child 328
16219bef66ec

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      }

mercurial