a323c55162
Change-Id: I4d492a63a41880ef8cd69321372a4853825b9efd Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/426321 Reviewed-by: Liam Appelbe <liama@google.com> Auto-Submit: Bob Nystrom <rnystrom@google.com> Commit-Queue: Liam Appelbe <liama@google.com>
107 lines
2.7 KiB
Dart
107 lines
2.7 KiB
Dart
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
import 'dart:async';
|
|
import 'dart:io';
|
|
import 'dart:isolate';
|
|
|
|
import 'package:http/http.dart' as http;
|
|
|
|
void main() async {
|
|
// Start a server to obtain a randomly assigned, free port.
|
|
final mainServer = await HttpServer.bind('::1', 0, shared: true);
|
|
final sharedPort = mainServer.port;
|
|
|
|
final workers = List<ServerWorker>.generate(
|
|
4,
|
|
(i) => ServerWorker(i, sharedPort),
|
|
);
|
|
await Future.wait(workers.map((w) => w.start()));
|
|
mainServer.close();
|
|
|
|
await Future.delayed(Duration(seconds: 1));
|
|
// spawn client isolate
|
|
final clientisolate = await Isolate.spawn(client, sharedPort);
|
|
// Wait for 20 secs. It used to crash within 10 seconds.
|
|
await Future.delayed(Duration(seconds: 20));
|
|
|
|
workers.forEach((w) {
|
|
w.respawn = false;
|
|
w.terminate();
|
|
});
|
|
print('kill client isolates');
|
|
clientisolate.kill();
|
|
}
|
|
|
|
class ServerWorker {
|
|
final int workerid;
|
|
final int port;
|
|
Isolate? _isolate;
|
|
bool respawn = true;
|
|
|
|
ServerWorker(this.workerid, this.port);
|
|
|
|
Future<void> start() async {
|
|
final onExit = ReceivePort();
|
|
onExit.listen((_) {
|
|
onExit.close();
|
|
// Respawn another isolate
|
|
if (respawn) start();
|
|
});
|
|
final ready = ReceivePort();
|
|
_isolate = await Isolate.spawn(
|
|
_main,
|
|
[workerid, port, ready.sendPort],
|
|
errorsAreFatal: true,
|
|
onExit: onExit.sendPort,
|
|
);
|
|
await ready.first;
|
|
if (workerid == 0) terminate();
|
|
}
|
|
|
|
void terminate() {
|
|
Future.delayed(Duration(seconds: 1), () {
|
|
print('terminate ${workerid}');
|
|
_isolate?.kill();
|
|
_isolate = null;
|
|
});
|
|
}
|
|
|
|
static _main(List args) async {
|
|
final workerid = args[0] as int;
|
|
final port = args[1] as int;
|
|
final readyPort = args[2] as SendPort;
|
|
|
|
final server = await HttpServer.bind('::1', port, shared: true);
|
|
readyPort.send(null);
|
|
server.listen((HttpRequest request) {
|
|
print('from worker ${workerid}');
|
|
final response = request.response;
|
|
response.statusCode = HttpStatus.ok;
|
|
response.write('server worker ${workerid}');
|
|
response.close();
|
|
});
|
|
}
|
|
}
|
|
|
|
Future<String> get(Uri url) async {
|
|
while (true) {
|
|
try {
|
|
await http.get(url);
|
|
return '';
|
|
} catch (err) {}
|
|
}
|
|
}
|
|
|
|
void client(int port) async {
|
|
while (true) {
|
|
final futures = <Future>[];
|
|
final numAtOnce = 16; // enough to keep the server busy
|
|
for (int i = 0; i < numAtOnce; ++i) {
|
|
futures.add(get(Uri.http('localhost:$port', '')).then((_) {}));
|
|
}
|
|
await Future.wait(futures);
|
|
}
|
|
}
|