Source:
private static String preprocessQueryInternal(Optional<String> catalog, Optional<String> schema, String query, List<String> preprocessorCommand, Duration timeout) throws QueryPreprocessorException { AtomicReference<Process> processReference = new AtomicReference<>(); SettableFuture<String> resultFuture = SettableFuture.create(); Thread thread = new Thread(() -> { try { ProcessBuilder processBuilder = new ProcessBuilder(preprocessorCommand); processBuilder.redirectErrorStream(true); processBuilder.environment().put(ENV_PRESTO_CATALOG, catalog.orElse("")); processBuilder.environment().put(ENV_PRESTO_SCHEMA, schema.orElse("")); Process process = processBuilder.start(); try { OutputStream outputStream = process.getOutputStream(); outputStream.write(query.getBytes(UTF_8)); process.getOutputStream().flush(); process.getOutputStream().close(); String result = CharStreams.toString(new InputStreamReader(process.getInputStream(), UTF_8)); int exitCode = process.waitFor(); if (exitCode == 0) { resultFuture.set(result); } else { resultFuture.setException(new QueryPreprocessorException("Query preprocessor failed:\n\n" + result)); } } finally { process.destroyForcibly(); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); resultFuture.setException(new QueryPreprocessorException("Interrupted while preprocessing query")); } catch (Throwable e) { resultFuture.setException(new QueryPreprocessorException("Error preprocessing query: " + e.getMessage(), e)); } }); thread.setName("Query preprocessor"); thread.start(); try { return resultFuture.get(timeout.toMillis(), MILLISECONDS); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new QueryPreprocessorException("Interrupted while preprocessing query"); } catch (ExecutionException e) { Throwable cause = e.getCause(); propagateIfPossible(cause, QueryPreprocessorException.class); throw new QueryPreprocessorException("Error preprocessing query: " + cause.getMessage(), cause); } catch (TimeoutException e) { throw new QueryPreprocessorException("Timed out waiting for query preprocessor"); } finally { Process process = processReference.get(); if (process != null) { process.destroyForcibly(); } } }

Target:
private static String preprocessQueryInternal(Optional<String> catalog, Optional<String> schema, String query, List<String> preprocessorCommand, Duration timeout) throws QueryPreprocessorException { AtomicReference<Process> processReference = new AtomicReference<>(); Future<String> task = executeInNewThread("Query preprocessor", () -> { String result; int exitCode; try { ProcessBuilder processBuilder = new ProcessBuilder(preprocessorCommand); processBuilder.redirectErrorStream(true); processBuilder.environment().put(ENV_PRESTO_CATALOG, catalog.orElse("")); processBuilder.environment().put(ENV_PRESTO_SCHEMA, schema.orElse("")); Process process = processBuilder.start(); processReference.set(process); Future<?> writeOutput = null; try { writeOutput = executeInNewThread("Query preprocessor output", () -> { try (OutputStream outputStream = process.getOutputStream()) { outputStream.write(query.getBytes(UTF_8)); } return null; }); try (InputStream inputStream = process.getInputStream()) { result = CharStreams.toString(new InputStreamReader(inputStream, UTF_8)); } try { writeOutput.get(); } catch (ExecutionException e) { throw e.getCause(); } exitCode = process.waitFor(); } finally { process.destroyForcibly(); if (writeOutput != null) { writeOutput.cancel(true); } } } catch (QueryPreprocessorException e) { throw e; } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new QueryPreprocessorException("Interrupted while preprocessing query"); } catch (Throwable e) { throw new QueryPreprocessorException("Error preprocessing query: " + e.getMessage(), e); } if (exitCode != 0) { throw new QueryPreprocessorException("Query preprocessor failed:\n\n" + result); } return result; }); try { return task.get(timeout.toMillis(), MILLISECONDS); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new QueryPreprocessorException("Interrupted while preprocessing query"); } catch (ExecutionException e) { Throwable cause = e.getCause(); propagateIfPossible(cause, QueryPreprocessorException.class); throw new QueryPreprocessorException("Error preprocessing query: " + cause.getMessage(), cause); } catch (TimeoutException e) { throw new QueryPreprocessorException("Timed out waiting for query preprocessor after " + timeout); } finally { Process process = processReference.get(); if (process != null) { process.destroyForcibly(); } task.cancel(true); } }