Skip to content

Commit

Permalink
fix: manually pipe messages from child process sdtout/stderr (microso…
Browse files Browse the repository at this point in the history
  • Loading branch information
yury-s committed May 6, 2021
1 parent a95f8f3 commit 0fa416b
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 6 deletions.
4 changes: 3 additions & 1 deletion driver-bundle/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
</configuration>
</plugin>
</plugins>
</build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ private void installBrowsers() throws IOException, InterruptedException {
p.destroy();
throw new RuntimeException("Timed out waiting for browsers to install");
}
if (p.exitValue() != 0) {
throw new RuntimeException("Failed to install browsers, exit code: " + p.exitValue());
}
}

private static boolean isExecutable(Path filePath) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.microsoft.playwright;

import com.microsoft.playwright.impl.Driver;
import com.microsoft.playwright.impl.StreamRedirectThread;
import org.junit.jupiter.api.Test;

import java.nio.file.Files;
Expand All @@ -36,11 +37,13 @@ void playwrightCliInstalled() throws Exception {
assertTrue(Files.exists(cli));

ProcessBuilder pb = new ProcessBuilder(cli.toString(), "install");
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
Process p = pb.start();
StreamRedirectThread stdoutThread = new StreamRedirectThread(p.getInputStream(), System.out);
StreamRedirectThread stderrThread = new StreamRedirectThread(p.getErrorStream(), System.err);
boolean result = p.waitFor(1, TimeUnit.MINUTES);
assertTrue(result, "Timed out waiting for browsers to install");
stderrThread.terminateAndJoin();
stdoutThread.terminateAndJoin();
} catch (Exception e) {
e.printStackTrace();
assertNull(e);
Expand Down
3 changes: 3 additions & 0 deletions driver/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
</configuration>
</plugin>
</plugins>
</build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.microsoft.playwright.impl;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

// We manually copy stderr and stdout from child process as INHERIT for err/out streams
// doesn't work well in Java Enterprise, see
// https://github.com/microsoft/playwright-java/issues/418#issuecomment-832650650
public class StreamRedirectThread extends Thread {
private final InputStream from;
private final OutputStream to;
private volatile boolean terminated;

public StreamRedirectThread(InputStream from, OutputStream to) {
this.from = from;
this.to = to;
start();
}

@Override
public void run() {
byte[] buffer = new byte[1<<14];
try {
while (true) {
while (from.available() != 0) {
int len = from.read(buffer);
if (len != -1) {
to.write(buffer);
}
}
if (terminated) {
break;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
} catch (IOException e) {
e.printStackTrace(System.err);
}
}

public void terminateAndJoin() {
terminated = true;
try {
join();
} catch (InterruptedException e) {
e.printStackTrace(System.err);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,16 @@ public String poll(Duration timeout) {
throw new PlaywrightException("Playwright connection closed");
}
try {
return incoming.poll(timeout.toMillis(), TimeUnit.MILLISECONDS);
String message = incoming.poll(timeout.toMillis(), TimeUnit.MILLISECONDS);
if (message == null && readerThread.exception != null) {
try {
close();
} catch (IOException e) {
e.printStackTrace(System.err);
}
throw new PlaywrightException("Failed to read message from driver, pipe closed.", readerThread.exception);
}
return message;
} catch (InterruptedException e) {
throw new PlaywrightException("Failed to read message", e);
}
Expand All @@ -84,6 +93,7 @@ class ReaderThread extends Thread {
private final DataInputStream in;
private final BlockingQueue<String> queue;
volatile boolean isClosing;
volatile Exception exception;

private static int readIntLE(DataInputStream in) throws IOException {
int ch1 = in.read();
Expand All @@ -109,7 +119,7 @@ public void run() {
queue.put(readMessage());
} catch (IOException e) {
if (!isInterrupted() && !isClosing) {
e.printStackTrace();
exception = e;
}
break;
} catch (InterruptedException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,29 @@

public class PlaywrightImpl extends ChannelOwner implements Playwright {
private Process driverProcess;
private StreamRedirectThread stderrThread;

public static PlaywrightImpl create() {
StreamRedirectThread stderrThread = null;
try {
Path driver = Driver.ensureDriverInstalled();
ProcessBuilder pb = new ProcessBuilder(driver.toString(), "run-driver");
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
// pb.environment().put("DEBUG", "pw:pro*");
Process p = pb.start();
stderrThread = new StreamRedirectThread(p.getErrorStream(), System.err);
Connection connection = new Connection(new PipeTransport(p.getInputStream(), p.getOutputStream()));
PlaywrightImpl result = (PlaywrightImpl) connection.waitForObjectWithKnownName("Playwright");
result.driverProcess = p;
result.stderrThread = stderrThread;
stderrThread = null;
result.initSharedSelectors(null);
return result;
} catch (IOException e) {
throw new PlaywrightException("Failed to launch driver", e);
} finally {
if (stderrThread != null) {
stderrThread.terminateAndJoin();
}
}
}

Expand Down Expand Up @@ -103,6 +111,7 @@ public void close() {
if (!didClose) {
System.err.println("WARNING: Timed out while waiting for driver process to exit");
}
stderrThread.terminateAndJoin();
} catch (IOException e) {
throw new PlaywrightException("Failed to terminate", e);
} catch (InterruptedException e) {
Expand Down

0 comments on commit 0fa416b

Please sign in to comment.