4242import java .util .HashMap ;
4343import java .util .List ;
4444import java .util .Map ;
45+ import java .util .concurrent .CompletableFuture ;
46+ import java .util .concurrent .ExecutionException ;
4547import java .util .concurrent .TimeUnit ;
46- import java .util .concurrent .atomic .AtomicBoolean ;
47- import java .util .concurrent .atomic .AtomicInteger ;
48+ import java .util .concurrent .TimeoutException ;
4849import java .util .concurrent .atomic .AtomicReference ;
4950import java .util .regex .Matcher ;
5051import java .util .regex .Pattern ;
@@ -62,6 +63,9 @@ public class ChromeLauncher implements AutoCloseable {
6263
6364 private static final Logger LOGGER = LoggerFactory .getLogger (ChromeLauncher .class );
6465
66+ private static final Logger CHROME_OUTPUT_LOGGER =
67+ LoggerFactory .getLogger (ChromeLauncher .class .getPackage ().getName () + ".chrome.output" );
68+
6569 private static final String TEMP_PREFIX = "cdt-user-data-dir" ;
6670
6771 private static final Pattern DEVTOOLS_LISTENING_LINE_PATTERN =
@@ -321,8 +325,7 @@ private int launchChromeProcess(Path chromeBinary, ChromeArguments chromeArgumen
321325 * @throws ChromeProcessTimeoutException If timeout expired while waiting for chrome process.
322326 */
323327 private int waitForDevToolsServer (final Process process ) throws ChromeProcessTimeoutException {
324- final AtomicInteger port = new AtomicInteger ();
325- final AtomicBoolean success = new AtomicBoolean (false );
328+ final CompletableFuture <Integer > port = new CompletableFuture <>();
326329 final AtomicReference <String > chromeOutput = new AtomicReference <>("" );
327330
328331 Thread readLineThread =
@@ -336,21 +339,36 @@ private int waitForDevToolsServer(final Process process) throws ChromeProcessTim
336339 // Wait for DevTools listening line and extract port number.
337340 String line ;
338341 while ((line = reader .readLine ()) != null ) {
339- Matcher matcher = DEVTOOLS_LISTENING_LINE_PATTERN .matcher (line );
340- if (matcher .find ()) {
341- port .set (Integer .parseInt (matcher .group (1 )));
342- success .set (true );
343- break ;
344- }
345-
346- if (chromeOutputBuilder .length () != 0 ) {
347- chromeOutputBuilder .append (System .lineSeparator ());
342+ CHROME_OUTPUT_LOGGER .debug (line );
343+
344+ if (!port .isDone ()) {
345+ Matcher matcher = DEVTOOLS_LISTENING_LINE_PATTERN .matcher (line );
346+ if (matcher .find ()) {
347+ port .complete (Integer .parseInt (matcher .group (1 )));
348+ if (!CHROME_OUTPUT_LOGGER .isDebugEnabled ()) {
349+ // no need to keep reading, ending the thread
350+ break ;
351+ }
352+
353+ // no longer needed, clearing
354+ chromeOutputBuilder = null ;
355+ chromeOutput .set (null );
356+ } else {
357+ if (chromeOutputBuilder .length () != 0 ) {
358+ chromeOutputBuilder .append (System .lineSeparator ());
359+ }
360+ chromeOutputBuilder .append (line );
361+ chromeOutput .set (chromeOutputBuilder .toString ());
362+ }
348363 }
349- chromeOutputBuilder .append (line );
350- chromeOutput .set (chromeOutputBuilder .toString ());
351364 }
352365 } catch (Exception e ) {
353- LOGGER .error ("Failed while waiting for dev tools server." , e );
366+ if (port .isDone ()) {
367+ LOGGER .debug ("Error while reading Chrome process output." , e );
368+ } else {
369+ LOGGER .error ("Failed while waiting for dev tools server." , e );
370+ port .completeExceptionally (e );
371+ }
354372 } finally {
355373 closeQuietly (reader );
356374 }
@@ -359,24 +377,24 @@ private int waitForDevToolsServer(final Process process) throws ChromeProcessTim
359377 readLineThread .start ();
360378
361379 try {
362- readLineThread .join (TimeUnit .SECONDS .toMillis (configuration .getStartupWaitTime ()));
363-
364- if (!success .get ()) {
365- close (readLineThread );
380+ return port .get (configuration .getStartupWaitTime (), TimeUnit .SECONDS );
381+ } catch (TimeoutException e ) {
382+ close (readLineThread );
366383
367- throw new ChromeProcessTimeoutException (
368- "Failed while waiting for chrome to start: "
369- + "Timeout expired! Chrome output: "
370- + chromeOutput .get ());
371- }
384+ throw new ChromeProcessTimeoutException (
385+ "Failed while waiting for chrome to start: "
386+ + "Timeout expired! Chrome output: "
387+ + chromeOutput .get ());
372388 } catch (InterruptedException e ) {
373389 close (readLineThread );
374390
375391 LOGGER .error ("Interrupted while waiting for dev tools server." , e );
376392 throw new RuntimeException ("Interrupted while waiting for dev tools server." , e );
393+ } catch (ExecutionException e ) {
394+ close (readLineThread );
395+ // exception already logged before completeExceptionally
396+ throw new RuntimeException ("Failed while waiting for dev tools server." , e );
377397 }
378-
379- return port .get ();
380398 }
381399
382400 private void close (Thread thread ) {
0 commit comments