Browse Source

Fix an uncaught exception during dart startup (#3640)

Here's an example of the error output from before this change:

Unhandled exception:
Bad state: Stream was already listened to
#0      _RawServerSocket.listen (dart:io-patch/socket_patch.dart:1106)
#1      new _ForwardingStreamSubscription (dart:async/stream_pipe.dart:123)
#2      _ForwardingStream._createSubscription (dart:async/stream_pipe.dart:91)
#3      _ForwardingStream.listen (dart:async/stream_pipe.dart:86)
#4      _ServerSocket.listen (dart:io-patch/socket_patch.dart:1351)
#5      _HttpServer.listen (dart:io/http_impl.dart:2278)
#6      _startServer.<anonymous closure> (file:///server.dart:88:12)
#7      _RootZone.runUnary (dart:async/zone.dart:1371)
#8      _FutureListener.handleValue (dart:async/future_impl.dart:129)
#9      _Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:636)
#10     _Future._propagateToListeners (dart:async/future_impl.dart:665)
#11     _Future._completeWithValue (dart:async/future_impl.dart:478)
#12     Future.wait.<anonymous closure> (dart:async/future.dart:362)
#13     _RootZone.runUnary (dart:async/zone.dart:1371)
#14     _FutureListener.handleValue (dart:async/future_impl.dart:129)
#15     _Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:636)
#16     _Future._propagateToListeners (dart:async/future_impl.dart:665)
#17     _Future._completeWithValue (dart:async/future_impl.dart:478)
#18     Future.wait.<anonymous closure> (dart:async/future.dart:362)
#19     _RootZone.runUnary (dart:async/zone.dart:1371)
#20     _FutureListener.handleValue (dart:async/future_impl.dart:129)
#21     _Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:636)
#22     _Future._propagateToListeners (dart:async/future_impl.dart:665)
#23     _Future._completeWithValue (dart:async/future_impl.dart:478)
#24     _Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:510)
#25     _microtaskLoop (dart:async/schedule_microtask.dart:41)
#26     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50)
#27     _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:99)
#28     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:152)
Michael Hixson 7 years ago
parent
commit
04dd98d23e

+ 6 - 2
frameworks/Dart/dart/dart.dockerfile

@@ -1,7 +1,11 @@
 FROM google/dart:1.24
 
-COPY ./ ./
+WORKDIR /dart_app
+COPY fortunes.mustache fortunes.mustache
+COPY postgresql.yaml postgresql.yaml
+COPY pubspec.yaml pubspec.yaml
+COPY server.dart server.dart
 
 RUN pub upgrade
 
-CMD dart server.dart -a 0.0.0.0 -p 8080 -i $(nproc)
+CMD ["dart", "server.dart"]

+ 1 - 1
frameworks/Dart/dart/pubspec.yaml

@@ -3,8 +3,8 @@ description: A benchmark of dart
 environment:
   sdk: '>=1.6.0 <2.0.0'
 dependencies:
-  args: 0.12.0+2
   crypto: 0.9.0
   mustache: 0.1.8
   postgresql: 0.2.14
+  system_info: 0.0.16
   yaml: 2.0.1+1

+ 21 - 27
frameworks/Dart/dart/server.dart

@@ -2,35 +2,30 @@ import 'dart:async' show Future;
 import 'dart:convert';
 import 'dart:io';
 import 'dart:isolate';
-import 'dart:math' show Random;
-import 'package:args/args.dart' show ArgParser;
+import 'dart:math' show Random, max;
 import 'package:mustache/mustache.dart' as mustache;
 import 'package:postgresql/postgresql.dart' as pg;
 import 'package:postgresql/postgresql_pool.dart' as pgpool;
+import 'package:system_info/system_info.dart';
 import 'package:yaml/yaml.dart' as yaml;
 
+final _NUM_PROCESSORS = SysInfo.processors.length;
+
 final _encoder = new JsonUtf8Encoder();
 
-/// Starts a new HTTP server that implements the tests to be benchmarked.  The
-/// address and port for incoming connections is configurable via command line
-/// arguments, as is the number of database connections to be maintained in the
-/// connection pool.
 void main(List<String> args) {
-  var parser = new ArgParser()
-    ..addOption('address', abbr: 'a', defaultsTo: '0.0.0.0')
-    ..addOption('port', abbr: 'p', defaultsTo: '8080')
-    ..addOption('dbconnections', abbr: 'd', defaultsTo: '256')
-    ..addOption('isolates', abbr: 'i', defaultsTo: '1');
-  var arguments = parser.parse(args);
-  var isolates = int.parse(arguments['isolates']);
-  var dbConnections = int.parse(arguments['dbconnections']) ~/ isolates;
-  ServerSocket
-      .bind(arguments['address'], int.parse(arguments['port']), shared: true)
-      .then((server) {
-        for (int i = 1; i < isolates; i++) {
-          _startServer(server, dbConnections);
-        }
-  });
+  ReceivePort errorPort = new ReceivePort();
+  errorPort.listen((e) => print(e));
+  for (int i = 0; i < _NUM_PROCESSORS; i++) {
+    Isolate.spawn(
+        startInIsolate,
+        [],
+        onError: errorPort.sendPort);
+  }
+}
+
+void startInIsolate(List args) {
+  _startServer();
 }
 
 /// The entity used in the database query and update tests.
@@ -67,11 +62,10 @@ pgpool.Pool _connectionPool;
 /// The mustache template which is rendered in the fortunes test.
 mustache.Template _fortunesTemplate;
 
-/// Starts a benchmark server, which listens for connections from
-/// '[address] : [port]' and maintains [dbConnections] connections to the
-/// database.
-void _startServer(serverSocket, dbConnections) {
+void _startServer() {
+  var dbConnections = max(1, (256 / _NUM_PROCESSORS).floor());
   Future.wait([
+    HttpServer.bind("0.0.0.0", 8080, shared: true),
     new File('postgresql.yaml').readAsString().then((config) {
       _connectionPool = new pgpool.Pool(
           new pg.Settings.fromMap(yaml.loadYaml(config)).toUri(),
@@ -81,8 +75,8 @@ void _startServer(serverSocket, dbConnections) {
     new File('fortunes.mustache').readAsString().then((template) {
       _fortunesTemplate = mustache.parse(template);
     })
-  ]).then((_) {
-    var server = new HttpServer.listenOn(serverSocket);
+  ]).then((List waitResults) {
+    var server = waitResults[0];
     server.defaultResponseHeaders.clear();
     server.serverHeader = 'dart';
     server.listen((request) {