Skip to content

Commit 61fa884

Browse files
author
Anna Gringauze
authored
Recover from used port errors when starting debug service (#1379)
Closes: #1378
1 parent 3a9e6b9 commit 61fa884

File tree

6 files changed

+35
-9
lines changed

6 files changed

+35
-9
lines changed

dwds/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 11.2.1-dev
2+
3+
- Recover from used port errors when starting debug service.
4+
15
## 11.2.0
26

37
- Throw `SentinelException` instead of `RPCError` on vm service

dwds/lib/src/services/debug_service.dart

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import 'dart:math';
1111
import 'dart:typed_data';
1212

1313
import 'package:dds/dds.dart';
14-
import 'package:http_multi_server/http_multi_server.dart';
1514
import 'package:pedantic/pedantic.dart';
1615
import 'package:shelf/shelf.dart' as shelf;
1716
import 'package:shelf/shelf.dart' hide Response;
@@ -253,13 +252,12 @@ class DebugService {
253252
return innerHandler(request);
254253
};
255254
}
256-
var port = await findUnusedPort();
257-
var server = await HttpMultiServer.bind(hostname, port);
255+
var server = await startHttpServer(hostname);
258256
serveRequests(server, handler);
259257
return DebugService._(
260258
chromeProxyService,
261259
server.address.host,
262-
port,
260+
server.port,
263261
authToken,
264262
serviceExtensionRegistry,
265263
server,

dwds/lib/src/utilities/shared.dart

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import 'dart:io';
88

9+
import 'package:http_multi_server/http_multi_server.dart';
910
import 'package:vm_service/vm_service.dart';
1011
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
1112

@@ -47,6 +48,28 @@ Future<int> findUnusedPort() async {
4748
return port;
4849
}
4950

51+
/// Finds unused port and binds a new http server to it.
52+
///
53+
/// Retries a few times to recover from errors due to
54+
/// another thread or process opening the same port.
55+
Future<HttpServer> startHttpServer(String hostname, {int port}) async {
56+
HttpServer httpServer;
57+
var retries = 5;
58+
var i = 0;
59+
while (i < retries) {
60+
i++;
61+
try {
62+
httpServer =
63+
await HttpMultiServer.bind(hostname, port ?? await findUnusedPort());
64+
} on SocketException {
65+
if (i == retries) rethrow;
66+
}
67+
if (httpServer != null || i == retries) return httpServer;
68+
await Future<void>.delayed(const Duration(milliseconds: 100));
69+
}
70+
return httpServer;
71+
}
72+
5073
/// Throws an [ExceptionDetails] object if `exceptionDetails` is present on the
5174
/// result.
5275
void handleErrorIfPresent(WipResponse response,

dwds/lib/src/version.dart

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dwds/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: dwds
22
# Every time this changes you need to run `pub run build_runner build`.
3-
version: 11.2.0
3+
version: 11.2.1-dev
44
homepage: https://github.com/dart-lang/webdev/tree/master/dwds
55
description: >-
66
A service that proxies between the Chrome debug protocol and the Dart VM

dwds/test/expression_compiler_service_test.dart

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import 'dart:io';
1010

1111
import 'package:dwds/dwds.dart';
1212
import 'package:dwds/src/utilities/shared.dart';
13-
import 'package:http_multi_server/http_multi_server.dart';
1413
import 'package:path/path.dart' as p;
1514
import 'package:shelf/shelf.dart';
1615
import 'package:shelf/shelf_io.dart' as shelf_io;
@@ -53,8 +52,11 @@ void main() async {
5352
customLogWriter: (level, message, {error, loggerName, stackTrace}) =>
5453
output.add('[$level] $loggerName: $message'));
5554

55+
// start asset server
56+
server = await startHttpServer('localhost');
57+
var port = server.port;
58+
5659
// start expression compilation service
57-
final port = await findUnusedPort();
5860
final assetHandler = (request) =>
5961
Response(200, body: File.fromUri(kernel).readAsBytesSync());
6062
service =
@@ -63,7 +65,6 @@ void main() async {
6365
await service.initialize(moduleFormat: 'amd');
6466

6567
// setup asset server
66-
server = await HttpMultiServer.bind('localhost', port);
6768
shelf_io.serveRequests(
6869
server, Cascade().add(service.handler).add(assetHandler).handler);
6970

0 commit comments

Comments
 (0)