[vm_service] Fix socket exhaustion in resume_shutdown_race_test

The resumer in `resume_shutdown_race_test.dart` was running in a tight
`do-while` loop, hammering the VM server with `getVM` and `getIsolate`
requests to check if all isolates are paused at exit. During VM
shutdown, this rapid sequence of requests could cause socket exhaustion,
especially on Windows, or trigger transient connection errors.

This is fixed by adding a 10ms delay using `Future.delayed` at the end
of each iteration, and wrapping the loop's HTTP request block in a
`try-catch` block to gracefully log and ignore transient connection or
request errors during VM shutdown.

Change-Id: I1bfcad7505254a1feb59dfb654421547efc02d46
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/508720
Commit-Queue: Ben Konyi <bkonyi@google.com>
Reviewed-by: Mark Zhou <markzipan@google.com>
Auto-Submit: Ben Konyi <bkonyi@google.com>
Commit-Queue: Mark Zhou <markzipan@google.com>
This commit is contained in:
Ben Konyi
2026-06-02 13:22:38 -07:00
committed by dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent 3f7dd5c075
commit 0e535e710b
@@ -50,16 +50,25 @@ Future<Never> resumer(_) async {
// Wait for the main isolate and children to all be paused at exit.
final paused = <String>[];
do {
paused.clear();
final vm = (await get('getVM', {}))['result'];
for (Map<String, dynamic> isolate in vm['isolates']) {
final id = isolate['id'];
isolate = (await get('getIsolate', {'isolateId': id}))['result'];
if ((isolate['pauseEvent'] != null) &&
(isolate['pauseEvent']['kind'] == 'PauseExit')) {
paused.add(id);
try {
paused.clear();
final vmResult = await get('getVM', {});
final vm = vmResult['result'];
if (vm != null) {
for (Map<String, dynamic> isolate in vm['isolates']) {
final id = isolate['id'];
final isolateResult = await get('getIsolate', {'isolateId': id});
isolate = isolateResult['result'] ?? {};
if ((isolate['pauseEvent'] != null) &&
(isolate['pauseEvent']['kind'] == 'PauseExit')) {
paused.add(id);
}
}
}
} catch (e) {
print('Transient error in resumer: $e');
}
await Future.delayed(const Duration(milliseconds: 10));
} while (paused.length != childCount + 1);
// Resume the main isolate and children. When the main isolate resumes, it