Skip to content

Commit 3743293

Browse files
author
Anna Gringauze
authored
Fix race condition on simultaneous hot restarts (#1870)
* Wait for isolate to be destroyed before creating a new one * Update changelog * Fix race condition on simultaneous hot restarts - Fix race condition on running two `createIsolate` calls simultaneously. - Run `destroyIsolate` followed by `createIsolate` an atomic operation. - Make debugger API that depend on isolate running wait for the start of the app. - Make debugger API throw if the isolate exits while the API is waiting. - Fix exception on uninitialized `DwdsStats._devToolsStart` when using an observatory uri to connect to the dwds VM service. - Remove unnecessary async keywords from synchronoous debugger API. Closes: ihttps://github.com//issues/1869 * Fix race condition on simultaneous hot restarts - Fix race condition on running two `createIsolate` calls simultaneously. - Run `destroyIsolate` followed by `createIsolate` an atomic operation. - Make debugger API that depend on isolate running wait for the start of the app. - Make debugger API throw if the isolate exits while the API is waiting. - Fix exception on uninitialized `DwdsStats._devToolsStart` when using an observatory uri to connect to the dwds VM service. - Remove unnecessary async keywords from synchronoous debugger API. Closes: ihttps://github.com//issues/1869 * Keep race condition changes only * Revert unneded changes again * Merged with master * Update changelog, pubspec, and build * Make hot restart atomic changes only * Address CR Comments
1 parent 094ee97 commit 3743293

File tree

11 files changed

+583
-408
lines changed

11 files changed

+583
-408
lines changed

dwds/CHANGELOG.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,28 @@
1-
## 16.0.2-dev
1+
## 17.0.0-dev
22

33
- Include debug information in the event sent from the injected client to the
44
Dart Debug Extension notifying that the Dart app is ready.
5-
- Include an optional param to `Dwds.start` to indicate whether it is running
6-
internally or externally.
75
- Fix null cast error on expression evaluations after dwds fails to find class
86
metadata.
97
- Include the entire exception description up to the stacktrace in
108
`mapExceptionStackTrace`.
119
- Allow enabling experiments in the expression compiler service.
12-
- Include an optional param to `Dwds.start` to indicate whether it a Flutter app
13-
or not.
1410
- Pre-warm expression compiler cache to speed up Flutter Inspector loading.
15-
- Remove `ChromeProxyService.setExceptionPauseMode()`.
1611
- Display full error on failure to start DDS.
1712
- Fix crash on processing DevTools event when starting DevTools from DevTools
1813
uri.
1914
- Prepare or Dart 3 alpha breaking changes:
2015
- Move weak null safety tests to special branch of `build_web_compilers`.
2116
- Do not pass `--(no)-sound-null-safety` flag to build daemon.
2217
- Add back `ChromeProxyService.setExceptionPauseMode()` without override.
18+
- Make hot restart atomic to prevent races on simultaneous execution.
2319

20+
**Breaking changes**
21+
- Include an optional param to `Dwds.start` to indicate whether it is running
22+
internally or externally.
23+
- Include an optional param to `Dwds.start` to indicate whether it a Flutter app
24+
or not.
25+
- Remove deprecated `ChromeProxyService.setExceptionPauseMode()`.
2426

2527
## 16.0.1
2628

dwds/lib/src/debugging/debugger.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
import 'dart:async';
66
import 'dart:math' as math;
77

8+
import 'package:dwds/src/utilities/synchronized.dart';
89
import 'package:logging/logging.dart';
9-
import 'package:pool/pool.dart';
1010
import 'package:vm_service/vm_service.dart';
1111
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'
1212
hide StackTrace;
@@ -779,7 +779,7 @@ class _Breakpoints extends Domain {
779779

780780
final _bpByDartId = <String, Future<Breakpoint>>{};
781781

782-
final _pool = Pool(1);
782+
final _queue = AtomicQueue();
783783

784784
final Locations locations;
785785
final RemoteDebugger remoteDebugger;
@@ -868,7 +868,7 @@ class _Breakpoints extends Domain {
868868
final urlRegex = '.*${location.jsLocation.module}.*';
869869
// Prevent `Aww, snap!` errors when setting multiple breakpoints
870870
// simultaneously by serializing the requests.
871-
return _pool.withResource(() async {
871+
return _queue.run(() async {
872872
final breakPointId = await sendCommandAndValidateResult<String>(
873873
remoteDebugger,
874874
method: 'Debugger.setBreakpointByUrl',

dwds/lib/src/debugging/frame_computer.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
import 'package:pool/pool.dart';
5+
import 'package:dwds/src/utilities/synchronized.dart';
66
import 'package:vm_service/vm_service.dart';
77
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
88

@@ -11,9 +11,9 @@ import 'debugger.dart';
1111
class FrameComputer {
1212
final Debugger debugger;
1313

14-
// To ensure that the frames are computed only once, we use a pool to guard
15-
// the work. Frames are computed sequentially.
16-
final _pool = Pool(1);
14+
// To ensure that the frames are computed only once, we use an atomic queue
15+
// to guard the work. Frames are computed sequentially.
16+
final _queue = AtomicQueue();
1717

1818
final List<WipCallFrame> _callFrames;
1919
final List<Frame> _computedFrames = [];
@@ -36,7 +36,7 @@ class FrameComputer {
3636
/// Translates Chrome callFrames contained in [DebuggerPausedEvent] into Dart
3737
/// [Frame]s.
3838
Future<List<Frame>> calculateFrames({int? limit}) async {
39-
return _pool.withResource(() async {
39+
return _queue.run(() async {
4040
if (limit != null && _computedFrames.length >= limit) {
4141
return _computedFrames.take(limit).toList();
4242
}

dwds/lib/src/dwds_vm_client.dart

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import 'dart:async';
66
import 'dart:convert';
77

8+
import 'package:dwds/src/utilities/synchronized.dart';
89
import 'package:logging/logging.dart';
910
import 'package:uuid/uuid.dart';
1011
import 'package:vm_service/vm_service.dart';
@@ -32,6 +33,9 @@ class DwdsVmClient {
3233
/// All subsequent calls to [close] will return this future.
3334
Future<void>? _closed;
3435

36+
/// Synchronizes hot restarts to avoid races.
37+
final _hotRestartQueue = AtomicQueue();
38+
3539
DwdsVmClient(this.client, this._requestController, this._responseController);
3640

3741
Future<void> close() => _closed ??= () async {
@@ -60,6 +64,9 @@ class DwdsVmClient {
6064
final chromeProxyService =
6165
debugService.chromeProxyService as ChromeProxyService;
6266

67+
final dwdsVmClient =
68+
DwdsVmClient(client, requestController, responseController);
69+
6370
// Register '_flutter.listViews' method on the chrome proxy service vm.
6471
// In native world, this method is provided by the engine, but the web
6572
// engine is not aware of the VM uri or the isolates.
@@ -85,7 +92,7 @@ class DwdsVmClient {
8592
client.registerServiceCallback(
8693
'hotRestart',
8794
(request) => captureElapsedTime(
88-
() => _hotRestart(chromeProxyService, client),
95+
() => dwdsVmClient.hotRestart(chromeProxyService, client),
8996
(_) => DwdsEvent.hotRestart()));
9097
await client.registerService('hotRestart', 'DWDS');
9198

@@ -138,7 +145,12 @@ class DwdsVmClient {
138145
});
139146
await client.registerService('_yieldControlToDDS', 'DWDS');
140147

141-
return DwdsVmClient(client, requestController, responseController);
148+
return dwdsVmClient;
149+
}
150+
151+
Future<Map<String, dynamic>> hotRestart(
152+
ChromeProxyService chromeProxyService, VmService client) async {
153+
return _hotRestartQueue.run(() => _hotRestart(chromeProxyService, client));
142154
}
143155
}
144156

0 commit comments

Comments
 (0)