Skip to content

Commit 7ab9681

Browse files
committed
Read stdout and stderr in separate threads
Integration tests use boltkit to start database and cluster. Boltkit commands are invoked using Process API. Invocations sometimes hang on MacOS. This commit improves handling of stdout and stderr streams. Both are now read in parallel with waiting for command to finish. This prevents output bufferes from overflowing and might fix the hanging.
1 parent 6d818ba commit 7ab9681

File tree

1 file changed

+39
-5
lines changed

1 file changed

+39
-5
lines changed

driver/src/test/java/org/neo4j/driver/v1/util/cc/CommandLineUtil.java

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,23 @@
2323
import java.io.InputStream;
2424
import java.io.InputStreamReader;
2525
import java.util.List;
26+
import java.util.concurrent.Callable;
27+
import java.util.concurrent.ExecutorService;
28+
import java.util.concurrent.Executors;
29+
import java.util.concurrent.Future;
2630

31+
import org.neo4j.driver.v1.util.DaemonThreadFactory;
2732
import org.neo4j.driver.v1.util.ProcessEnvConfigurator;
2833

2934
import static java.lang.System.lineSeparator;
3035
import static java.util.Arrays.asList;
36+
import static java.util.concurrent.TimeUnit.MINUTES;
3137

3238
public class CommandLineUtil
3339
{
40+
private static final ExecutorService executor = Executors.newCachedThreadPool(
41+
new DaemonThreadFactory( "command-line-thread-" ) );
42+
3443
public static boolean boltKitAvailable()
3544
{
3645
try
@@ -59,8 +68,7 @@ public static String executeCommand( List<String> commands )
5968
catch ( InterruptedException e )
6069
{
6170
Thread.currentThread().interrupt();
62-
throw new CommandLineException( "Interrupted while waiting for command " +
63-
commands, e );
71+
throw new CommandLineException( "Interrupted while waiting for command " + commands, e );
6472
}
6573
}
6674

@@ -73,17 +81,31 @@ private static String executeAndGetStdOut( ProcessBuilder processBuilder )
7381
throws IOException, InterruptedException
7482
{
7583
Process process = processBuilder.start();
84+
Future<String> stdOutFuture = read( process.getInputStream() );
85+
Future<String> stdErrFuture = read( process.getErrorStream() );
7686
int exitCode = process.waitFor();
77-
String stdOut = asString( process.getInputStream() );
78-
String stdErr = asString( process.getErrorStream() );
87+
String stdOut = get( stdOutFuture );
88+
String stdErr = get( stdErrFuture );
7989
if ( exitCode != 0 )
8090
{
8191
throw new CommandLineException( "Non-zero exit code\nSTDOUT:\n" + stdOut + "\nSTDERR:\n" + stdErr );
8292
}
8393
return stdOut;
8494
}
8595

86-
private static String asString( InputStream input )
96+
private static Future<String> read( final InputStream input )
97+
{
98+
return executor.submit( new Callable<String>()
99+
{
100+
@Override
101+
public String call() throws Exception
102+
{
103+
return readToString( input );
104+
}
105+
} );
106+
}
107+
108+
private static String readToString( InputStream input )
87109
{
88110
StringBuilder result = new StringBuilder();
89111
try ( BufferedReader reader = new BufferedReader( new InputStreamReader( input ) ) )
@@ -100,4 +122,16 @@ private static String asString( InputStream input )
100122
}
101123
return result.toString();
102124
}
125+
126+
private static <T> T get( Future<T> future )
127+
{
128+
try
129+
{
130+
return future.get( 10, MINUTES );
131+
}
132+
catch ( Exception e )
133+
{
134+
throw new RuntimeException( e );
135+
}
136+
}
103137
}

0 commit comments

Comments
 (0)