Commit 367e11a4 authored by John McCutchan's avatar John McCutchan Committed by GitHub

Handle reassemble timeouts gracefully. (#9467)

- [x] Switch the reassemble timeout to 5 seconds.
- [x] Print a status message if reassemble fails:

```
Performing hot reload...
Reassembling app.flx$main took too long. Hot reload may have failed.
Reloaded 0 of 418 libraries in 5,322ms.
```

Fixes #9316
Fixes #8861
Fixes #8857
Fixes #8856
parent af25a5b8
...@@ -519,9 +519,15 @@ class HotRunner extends ResidentRunner { ...@@ -519,9 +519,15 @@ class HotRunner extends ResidentRunner {
await _evictDirtyAssets(); await _evictDirtyAssets();
printTrace('Reassembling application'); printTrace('Reassembling application');
bool reassembleAndScheduleErrors = false; bool reassembleAndScheduleErrors = false;
bool reassembleTimedOut = false;
for (FlutterView view in reassembleViews) { for (FlutterView view in reassembleViews) {
try { try {
await view.uiIsolate.flutterReassemble(); await view.uiIsolate.flutterReassemble();
} on TimeoutException {
reassembleTimedOut = true;
printTrace("Reassembling ${view.uiIsolate.name} took too long. ");
printStatus("Hot reloading ${view.uiIsolate.name} took too long. Hot reload may have failed.");
continue;
} catch (error) { } catch (error) {
reassembleAndScheduleErrors = true; reassembleAndScheduleErrors = true;
printError('Reassembling ${view.uiIsolate.name} failed: $error'); printError('Reassembling ${view.uiIsolate.name} failed: $error');
...@@ -548,7 +554,12 @@ class HotRunner extends ResidentRunner { ...@@ -548,7 +554,12 @@ class HotRunner extends ResidentRunner {
benchmarkData['hotReloadMillisecondsToFrame'] = benchmarkData['hotReloadMillisecondsToFrame'] =
reloadTimer.elapsed.inMilliseconds; reloadTimer.elapsed.inMilliseconds;
} }
if (shouldReportReloadTime) // Only report timings if we reloaded a single view without any
// errors or timeouts.
if ((reassembleViews.length == 1) &&
!reassembleAndScheduleErrors &&
!reassembleTimedOut &&
shouldReportReloadTime)
flutterUsage.sendTiming('hot', 'reload', reloadTimer.elapsed); flutterUsage.sendTiming('hot', 'reload', reloadTimer.elapsed);
return new OperationResult( return new OperationResult(
reassembleAndScheduleErrors ? 1 : OperationResult.ok.code, reassembleAndScheduleErrors ? 1 : OperationResult.ok.code,
......
...@@ -35,6 +35,9 @@ const Duration kDefaultRequestTimeout = const Duration(seconds: 30); ...@@ -35,6 +35,9 @@ const Duration kDefaultRequestTimeout = const Duration(seconds: 30);
/// Used for RPC requests that may take a long time. /// Used for RPC requests that may take a long time.
const Duration kLongRequestTimeout = const Duration(minutes: 1); const Duration kLongRequestTimeout = const Duration(minutes: 1);
/// Used for RPC requests that should never take a long time.
const Duration kShortRequestTimeout = const Duration(seconds: 5);
/// A connection to the Dart VM Service. /// A connection to the Dart VM Service.
class VMService { class VMService {
VMService._(this._peer, this.httpAddress, this.wsAddress, this._requestTimeout) { VMService._(this._peer, this.httpAddress, this.wsAddress, this._requestTimeout) {
...@@ -1005,8 +1008,8 @@ class Isolate extends ServiceObjectOwner { ...@@ -1005,8 +1008,8 @@ class Isolate extends ServiceObjectOwner {
Future<Map<String, dynamic>> flutterReassemble() async { Future<Map<String, dynamic>> flutterReassemble() async {
return await invokeFlutterExtensionRpcRaw( return await invokeFlutterExtensionRpcRaw(
'ext.flutter.reassemble', 'ext.flutter.reassemble',
timeout: kLongRequestTimeout, timeout: kShortRequestTimeout,
timeoutFatal: false, timeoutFatal: true,
); );
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment