[flutter_tools] retry chrome launch up to 3 times (#85162)
This commit is contained in:
@@ -249,7 +249,9 @@ class ChromiumLauncher {
|
||||
|
||||
// Keep attempting to launch the browser until one of:
|
||||
// - Chrome launched successfully, in which case we just return from the loop.
|
||||
// - The tool detected an unretriable Chrome error, in which case we throw ToolExit.
|
||||
// - The tool reached the maximum retry count, in which case we throw ToolExit.
|
||||
const int kMaxRetries = 3;
|
||||
int retry = 0;
|
||||
while (true) {
|
||||
final Process process = await _processManager.start(args);
|
||||
|
||||
@@ -263,6 +265,7 @@ class ChromiumLauncher {
|
||||
// Wait until the DevTools are listening before trying to connect. This is
|
||||
// only required for flutter_test --platform=chrome and not flutter run.
|
||||
bool hitGlibcBug = false;
|
||||
bool shouldRetry = false;
|
||||
await process.stderr
|
||||
.transform(utf8.decoder)
|
||||
.transform(const LineSplitter())
|
||||
@@ -270,6 +273,7 @@ class ChromiumLauncher {
|
||||
_logger.printTrace('[CHROME]:$line');
|
||||
if (line.contains(_kGlibcError)) {
|
||||
hitGlibcBug = true;
|
||||
shouldRetry = true;
|
||||
}
|
||||
return line;
|
||||
})
|
||||
@@ -282,17 +286,22 @@ class ChromiumLauncher {
|
||||
// Return value unused.
|
||||
return '';
|
||||
}
|
||||
_logger.printTrace('Failed to launch browser. Command used to launch it: ${args.join(' ')}');
|
||||
throw ToolExit(
|
||||
'Failed to launch browser. Make sure you are using an up-to-date '
|
||||
'Chrome or Edge. Otherwise, consider using -d web-server instead '
|
||||
'and filing an issue at https://github.com/flutter/flutter/issues.',
|
||||
);
|
||||
if (retry >= kMaxRetries) {
|
||||
_logger.printTrace('Failed to launch browser after $kMaxRetries tries. Command used to launch it: ${args.join(' ')}');
|
||||
throw ToolExit(
|
||||
'Failed to launch browser. Make sure you are using an up-to-date '
|
||||
'Chrome or Edge. Otherwise, consider using -d web-server instead '
|
||||
'and filing an issue at https://github.com/flutter/flutter/issues.',
|
||||
);
|
||||
}
|
||||
shouldRetry = true;
|
||||
return '';
|
||||
});
|
||||
|
||||
if (!hitGlibcBug) {
|
||||
if (!hitGlibcBug && !shouldRetry) {
|
||||
return process;
|
||||
}
|
||||
retry += 1;
|
||||
|
||||
// A precaution that avoids accumulating browser processes, in case the
|
||||
// glibc bug doesn't cause the browser to quit and we keep looping and
|
||||
|
||||
@@ -461,22 +461,61 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('gives up retrying when a non-glibc error happens', () async {
|
||||
testWithoutContext('can retry launch when chrome fails to start', () async {
|
||||
const List<String> args = <String>[
|
||||
'example_chrome',
|
||||
'--user-data-dir=/.tmp_rand0/flutter_tools_chrome_device.rand0',
|
||||
'--remote-debugging-port=12345',
|
||||
...kChromeArgs,
|
||||
'--headless',
|
||||
'--disable-gpu',
|
||||
'--no-sandbox',
|
||||
'--window-size=2400,1800',
|
||||
'example_url',
|
||||
];
|
||||
|
||||
// Pretend to random error 3 times.
|
||||
for (int i = 0; i < 3; i++) {
|
||||
processManager.addCommand(const FakeCommand(
|
||||
command: args,
|
||||
stderr: 'BLAH BLAH',
|
||||
));
|
||||
}
|
||||
|
||||
// Succeed on the 4th try.
|
||||
processManager.addCommand(const FakeCommand(
|
||||
command: <String>[
|
||||
'example_chrome',
|
||||
'--user-data-dir=/.tmp_rand0/flutter_tools_chrome_device.rand0',
|
||||
'--remote-debugging-port=12345',
|
||||
...kChromeArgs,
|
||||
'--headless',
|
||||
'--disable-gpu',
|
||||
'--no-sandbox',
|
||||
'--window-size=2400,1800',
|
||||
'example_url',
|
||||
],
|
||||
stderr: 'nothing in the std error indicating glibc error',
|
||||
command: args,
|
||||
stderr: kDevtoolsStderr,
|
||||
));
|
||||
|
||||
expect(
|
||||
() async => chromeLauncher.launch(
|
||||
'example_url',
|
||||
skipCheck: true,
|
||||
headless: true,
|
||||
),
|
||||
returnsNormally,
|
||||
);
|
||||
});
|
||||
|
||||
testWithoutContext('gives up retrying when an error happens more than 3 times', () async {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
processManager.addCommand(const FakeCommand(
|
||||
command: <String>[
|
||||
'example_chrome',
|
||||
'--user-data-dir=/.tmp_rand0/flutter_tools_chrome_device.rand0',
|
||||
'--remote-debugging-port=12345',
|
||||
...kChromeArgs,
|
||||
'--headless',
|
||||
'--disable-gpu',
|
||||
'--no-sandbox',
|
||||
'--window-size=2400,1800',
|
||||
'example_url',
|
||||
],
|
||||
stderr: 'nothing in the std error indicating glibc error',
|
||||
));
|
||||
}
|
||||
|
||||
expect(
|
||||
() async => chromeLauncher.launch(
|
||||
'example_url',
|
||||
|
||||
Reference in New Issue
Block a user