Skip to content

Commit

Permalink
copy the glibc fix to felt (flutter#22878)
Browse files Browse the repository at this point in the history
  • Loading branch information
yjbanov authored Dec 4, 2020
1 parent 47add1d commit ff87b1d
Showing 1 changed file with 71 additions and 1 deletion.
72 changes: 71 additions & 1 deletion lib/web_ui/dev/chrome.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

// @dart = 2.6
import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:pedantic/pedantic.dart';
Expand Down Expand Up @@ -76,7 +77,7 @@ class Chrome extends Browser {
];

final Process process =
await Process.start(installation.executable, args);
await _spawnChromiumProcess(installation.executable, args);

remoteDebuggerCompleter.complete(
getRemoteDebuggerUrl(Uri.parse('http://localhost:${kDevtoolsPort}')));
Expand All @@ -91,3 +92,72 @@ class Chrome extends Browser {
Chrome._(Future<Process> startBrowser(), this.remoteDebuggerUrl)
: super(startBrowser);
}

/// Used by [Chrome] to detect a glibc bug and retry launching the
/// browser.
///
/// Once every few thousands of launches we hit this glibc bug:
///
/// https://sourceware.org/bugzilla/show_bug.cgi?id=19329.
///
/// When this happens Chrome spits out something like the following then exits with code 127:
///
/// Inconsistency detected by ld.so: ../elf/dl-tls.c: 493: _dl_allocate_tls_init: Assertion `listp->slotinfo[cnt].gen <= GL(dl_tls_generation)' failed!
const String _kGlibcError = 'Inconsistency detected by ld.so';

Future<Process> _spawnChromiumProcess(String executable, List<String> args, { String workingDirectory }) async {
// 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.
while (true) {
final Process process = await Process.start(executable, args, workingDirectory: workingDirectory);

process.stdout
.transform(utf8.decoder)
.transform(const LineSplitter())
.listen((String line) {
print('[CHROME STDOUT]: $line');
});

// 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;
await process.stderr
.transform(utf8.decoder)
.transform(const LineSplitter())
.map((String line) {
print('[CHROME STDERR]:$line');
if (line.contains(_kGlibcError)) {
hitGlibcBug = true;
}
return line;
})
.firstWhere((String line) => line.startsWith('DevTools listening'), orElse: () {
if (hitGlibcBug) {
print(
'Encountered glibc bug https://sourceware.org/bugzilla/show_bug.cgi?id=19329. '
'Will try launching browser again.',
);
return null;
}
print('Failed to launch browser. Command used to launch it: ${args.join(' ')}');
throw Exception(
'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 (!hitGlibcBug) {
return process;
}

// A precaution that avoids accumulating browser processes, in case the
// glibc bug doesn't cause the browser to quit and we keep looping and
// launching more processes.
process.exitCode.timeout(const Duration(seconds: 1), onTimeout: () {
process.kill();
return null;
});
}
}

0 comments on commit ff87b1d

Please sign in to comment.