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 =
@@ -319,8 +323,7 @@ private int launchChromeProcess(Path chromeBinary, ChromeArguments chromeArgumen
319323 * @throws ChromeProcessTimeoutException If timeout expired while waiting for chrome process.
320324 */
321325 private int waitForDevToolsServer (final Process process ) throws ChromeProcessTimeoutException {
322- final AtomicInteger port = new AtomicInteger ();
323- final AtomicBoolean success = new AtomicBoolean (false );
326+ final CompletableFuture <Integer > port = new CompletableFuture <>();
324327 final AtomicReference <String > chromeOutput = new AtomicReference <>("" );
325328
326329 Thread readLineThread =
@@ -334,21 +337,36 @@ private int waitForDevToolsServer(final Process process) throws ChromeProcessTim
334337 // Wait for DevTools listening line and extract port number.
335338 String line ;
336339 while ((line = reader .readLine ()) != null ) {
337- Matcher matcher = DEVTOOLS_LISTENING_LINE_PATTERN .matcher (line );
338- if (matcher .find ()) {
339- port .set (Integer .parseInt (matcher .group (1 )));
340- success .set (true );
341- break ;
342- }
343-
344- if (chromeOutputBuilder .length () != 0 ) {
345- chromeOutputBuilder .append (System .lineSeparator ());
340+ CHROME_OUTPUT_LOGGER .debug (line );
341+
342+ if (!port .isDone ()) {
343+ Matcher matcher = DEVTOOLS_LISTENING_LINE_PATTERN .matcher (line );
344+ if (matcher .find ()) {
345+ port .complete (Integer .parseInt (matcher .group (1 )));
346+ if (!CHROME_OUTPUT_LOGGER .isDebugEnabled ()) {
347+ // no need to keep reading, ending the thread
348+ break ;
349+ }
350+
351+ // no longer needed, clearing
352+ chromeOutputBuilder = null ;
353+ chromeOutput .set (null );
354+ } else {
355+ if (chromeOutputBuilder .length () != 0 ) {
356+ chromeOutputBuilder .append (System .lineSeparator ());
357+ }
358+ chromeOutputBuilder .append (line );
359+ chromeOutput .set (chromeOutputBuilder .toString ());
360+ }
346361 }
347- chromeOutputBuilder .append (line );
348- chromeOutput .set (chromeOutputBuilder .toString ());
349362 }
350363 } catch (Exception e ) {
351- LOGGER .error ("Failed while waiting for dev tools server." , e );
364+ if (port .isDone ()) {
365+ LOGGER .debug ("Error while reading Chrome process output." , e );
366+ } else {
367+ LOGGER .error ("Failed while waiting for dev tools server." , e );
368+ port .completeExceptionally (e );
369+ }
352370 } finally {
353371 closeQuietly (reader );
354372 }
@@ -357,24 +375,24 @@ private int waitForDevToolsServer(final Process process) throws ChromeProcessTim
357375 readLineThread .start ();
358376
359377 try {
360- readLineThread .join (TimeUnit .SECONDS .toMillis (configuration .getStartupWaitTime ()));
361-
362- if (!success .get ()) {
363- close (readLineThread );
378+ return port .get (configuration .getStartupWaitTime (), TimeUnit .SECONDS );
379+ } catch (TimeoutException e ) {
380+ close (readLineThread );
364381
365- throw new ChromeProcessTimeoutException (
366- "Failed while waiting for chrome to start: "
367- + "Timeout expired! Chrome output: "
368- + chromeOutput .get ());
369- }
382+ throw new ChromeProcessTimeoutException (
383+ "Failed while waiting for chrome to start: "
384+ + "Timeout expired! Chrome output: "
385+ + chromeOutput .get ());
370386 } catch (InterruptedException e ) {
371387 close (readLineThread );
372388
373389 LOGGER .error ("Interrupted while waiting for dev tools server." , e );
374390 throw new RuntimeException ("Interrupted while waiting for dev tools server." , e );
391+ } catch (ExecutionException e ) {
392+ close (readLineThread );
393+ // exception already logged before completeExceptionally
394+ throw new RuntimeException ("Failed while waiting for dev tools server." , e );
375395 }
376-
377- return port .get ();
378396 }
379397
380398 private void close (Thread thread ) {
0 commit comments