| OLD | NEW |
| 1 // Copyright (c) 2015, the Fletch project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Fletch project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE.md file. | 3 // BSD-style license that can be found in the LICENSE.md file. |
| 4 | 4 |
| 5 library fletchc.driver_main; | 5 library fletchc.driver_main; |
| 6 | 6 |
| 7 import 'dart:collection' show | 7 import 'dart:collection' show |
| 8 Queue; | 8 Queue; |
| 9 | 9 |
| 10 import 'dart:io' hide | 10 import 'dart:io' hide |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 import 'developer.dart' show | 73 import 'developer.dart' show |
| 74 combineTasks, | 74 combineTasks, |
| 75 allocateWorker; | 75 allocateWorker; |
| 76 | 76 |
| 77 import 'session_manager.dart' show | 77 import 'session_manager.dart' show |
| 78 lookupSession; | 78 lookupSession; |
| 79 | 79 |
| 80 import '../verbs/create_verb.dart' show | 80 import '../verbs/create_verb.dart' show |
| 81 CreateSessionTask; | 81 CreateSessionTask; |
| 82 | 82 |
| 83 import '../please_report_crash.dart' show |
| 84 crashReportRequested, |
| 85 requestBugReportOnOtherCrashMessage; |
| 86 |
| 83 Function gracefulShutdown; | 87 Function gracefulShutdown; |
| 84 | 88 |
| 85 class DriverCommandTransformerBuilder | 89 class DriverCommandTransformerBuilder |
| 86 extends CommandTransformerBuilder<Command> { | 90 extends CommandTransformerBuilder<Command> { |
| 87 Command makeCommand(int commandCode, ByteData payload) { | 91 Command makeCommand(int commandCode, ByteData payload) { |
| 88 DriverCommand code = DriverCommand.values[commandCode]; | 92 DriverCommand code = DriverCommand.values[commandCode]; |
| 89 switch (code) { | 93 switch (code) { |
| 90 case DriverCommand.Arguments: | 94 case DriverCommand.Arguments: |
| 91 return new Command(code, decodeArgumentsCommand(payload)); | 95 return new Command(code, decodeArgumentsCommand(payload)); |
| 92 | 96 |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 List<String> arguments = await client.arguments; | 232 List<String> arguments = await client.arguments; |
| 229 log.gotArguments(arguments); | 233 log.gotArguments(arguments); |
| 230 | 234 |
| 231 await handleVerb(arguments, client, pool); | 235 await handleVerb(arguments, client, pool); |
| 232 } | 236 } |
| 233 | 237 |
| 234 Future<Null> handleVerb( | 238 Future<Null> handleVerb( |
| 235 List<String> arguments, | 239 List<String> arguments, |
| 236 ClientController client, | 240 ClientController client, |
| 237 IsolatePool pool) async { | 241 IsolatePool pool) async { |
| 242 crashReportRequested = false; |
| 238 | 243 |
| 239 Future<int> performVerb() async { | 244 Future<int> performVerb() async { |
| 240 client.parseArguments(arguments); | 245 client.parseArguments(arguments); |
| 241 String sessionName = client.sentence.sessionName; | 246 String sessionName = client.sentence.sessionName; |
| 242 UserSession session; | 247 UserSession session; |
| 243 SharedTask initializer; | 248 SharedTask initializer; |
| 244 if (sessionName != null) { | 249 if (sessionName != null) { |
| 245 session = lookupSession(sessionName); | 250 session = lookupSession(sessionName); |
| 246 if (session == null) { | 251 if (session == null) { |
| 247 session = await createSession(sessionName, () => allocateWorker(pool)); | 252 session = await createSession(sessionName, () => allocateWorker(pool)); |
| 248 // TODO(ahe): packageRoot should be a user configurable option. | 253 // TODO(ahe): packageRoot should be a user configurable option. |
| 249 Uri packageRoot = client.sentence.base.resolve('package/'); | 254 Uri packageRoot = client.sentence.base.resolve('package/'); |
| 250 initializer = new CreateSessionTask(sessionName, packageRoot); | 255 initializer = new CreateSessionTask(sessionName, packageRoot); |
| 251 } | 256 } |
| 252 } | 257 } |
| 253 DriverVerbContext context = | 258 DriverVerbContext context = |
| 254 new DriverVerbContext(client, pool, session, initializer: initializer); | 259 new DriverVerbContext(client, pool, session, initializer: initializer); |
| 255 return await client.sentence.performVerb(context); | 260 return await client.sentence.performVerb(context); |
| 256 } | 261 } |
| 257 | 262 |
| 258 int exitCode = await runGuarded( | 263 int exitCode = await runGuarded( |
| 259 performVerb, | 264 performVerb, |
| 260 printLineOnStdout: client.printLineOnStdout, | 265 printLineOnStdout: client.printLineOnStdout, |
| 261 handleLateError: client.log.error) | 266 handleLateError: client.log.error) |
| 262 .catchError(client.reportErrorToClient, test: (e) => e is InputError) | 267 .catchError(client.reportErrorToClient, test: (e) => e is InputError) |
| 263 .catchError((error, StackTrace stackTrace) { | 268 .catchError((error, StackTrace stackTrace) { |
| 269 if (!crashReportRequested) { |
| 270 client.printLineOnStderr(requestBugReportOnOtherCrashMessage); |
| 271 crashReportRequested = true; |
| 272 } |
| 264 client.printLineOnStderr('$error'); | 273 client.printLineOnStderr('$error'); |
| 265 if (stackTrace != null) { | 274 if (stackTrace != null) { |
| 266 client.printLineOnStderr('$stackTrace'); | 275 client.printLineOnStderr('$stackTrace'); |
| 267 } | 276 } |
| 268 return COMPILER_EXITCODE_CRASH; | 277 return COMPILER_EXITCODE_CRASH; |
| 269 }); | 278 }); |
| 270 | 279 |
| 271 if (exitCode != null) { | 280 if (exitCode != null) { |
| 272 client.exit(exitCode); | 281 client.exit(exitCode); |
| 273 } | 282 } |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 /// [programName] is the canonicalized absolute path to the fletch | 418 /// [programName] is the canonicalized absolute path to the fletch |
| 410 /// executable (the C++ program). | 419 /// executable (the C++ program). |
| 411 String programName = sentence.programName; | 420 String programName = sentence.programName; |
| 412 String fletchVm = "$programName-vm"; | 421 String fletchVm = "$programName-vm"; |
| 413 this.sentence = analyzeSentence(sentence); | 422 this.sentence = analyzeSentence(sentence); |
| 414 this.fletchVm = fletchVm; | 423 this.fletchVm = fletchVm; |
| 415 return this.sentence; | 424 return this.sentence; |
| 416 } | 425 } |
| 417 | 426 |
| 418 int reportErrorToClient(InputError error, StackTrace stackTrace) { | 427 int reportErrorToClient(InputError error, StackTrace stackTrace) { |
| 428 if (!crashReportRequested) { |
| 429 printLineOnStderr(requestBugReportOnOtherCrashMessage); |
| 430 crashReportRequested = true; |
| 431 } |
| 419 printLineOnStderr(error.asDiagnostic().formatMessage()); | 432 printLineOnStderr(error.asDiagnostic().formatMessage()); |
| 420 if (error.kind == DiagnosticKind.internalError) { | 433 if (error.kind == DiagnosticKind.internalError) { |
| 421 printLineOnStderr('$stackTrace'); | 434 printLineOnStderr('$stackTrace'); |
| 422 return COMPILER_EXITCODE_CRASH; | 435 return COMPILER_EXITCODE_CRASH; |
| 423 } else { | 436 } else { |
| 424 return DART_VM_EXITCODE_COMPILE_TIME_ERROR; | 437 return DART_VM_EXITCODE_COMPILE_TIME_ERROR; |
| 425 } | 438 } |
| 426 } | 439 } |
| 427 } | 440 } |
| 428 | 441 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 440 /// A port used to read commands from the worker isolate. | 453 /// A port used to read commands from the worker isolate. |
| 441 ReceivePort workerReceivePort; | 454 ReceivePort workerReceivePort; |
| 442 | 455 |
| 443 /// When true, the worker can be shutdown by sending it a | 456 /// When true, the worker can be shutdown by sending it a |
| 444 /// DriverCommand.Signal command. Otherwise, it must be killed. | 457 /// DriverCommand.Signal command. Otherwise, it must be killed. |
| 445 bool eventLoopStarted = false; | 458 bool eventLoopStarted = false; |
| 446 | 459 |
| 447 /// Subscription for errors from [isolate]. | 460 /// Subscription for errors from [isolate]. |
| 448 StreamSubscription errorSubscription; | 461 StreamSubscription errorSubscription; |
| 449 | 462 |
| 463 bool crashReportRequested = false; |
| 464 |
| 450 IsolateController(this.isolate); | 465 IsolateController(this.isolate); |
| 451 | 466 |
| 452 /// Begin a session with the worker isolate. | 467 /// Begin a session with the worker isolate. |
| 453 Future<Null> beginSession() async { | 468 Future<Null> beginSession() async { |
| 454 errorSubscription = isolate.errors.listen(null); | 469 errorSubscription = isolate.errors.listen(null); |
| 455 errorSubscription.pause(); | 470 errorSubscription.pause(); |
| 456 workerReceivePort = isolate.beginSession(); | 471 workerReceivePort = isolate.beginSession(); |
| 457 Stream<Command> workerCommandStream = workerReceivePort.map( | 472 Stream<Command> workerCommandStream = workerReceivePort.map( |
| 458 (message) => new Command(DriverCommand.values[message[0]], message[1])); | 473 (message) => new Command(DriverCommand.values[message[0]], message[1])); |
| 459 workerCommands = new StreamIterator<Command>(workerCommandStream); | 474 workerCommands = new StreamIterator<Command>(workerCommandStream); |
| 460 if (!await workerCommands.moveNext()) { | 475 if (!await workerCommands.moveNext()) { |
| 461 // The worker must have been killed, or died in some other way. | 476 // The worker must have been killed, or died in some other way. |
| 462 // TODO(ahe): Add this assertion: assert(isolate.wasKilled); | 477 // TODO(ahe): Add this assertion: assert(isolate.wasKilled); |
| 463 endSession(); | 478 endSession(); |
| 464 return; | 479 return; |
| 465 } | 480 } |
| 466 Command command = workerCommands.current; | 481 Command command = workerCommands.current; |
| 467 assert(command.code == DriverCommand.SendPort); | 482 assert(command.code == DriverCommand.SendPort); |
| 468 assert(command.data != null); | 483 assert(command.data != null); |
| 469 workerSendPort = command.data; | 484 workerSendPort = command.data; |
| 470 } | 485 } |
| 471 | 486 |
| 472 /// Attach to a C++ client and forward commands to the worker isolate, and | 487 /// Attach to a C++ client and forward commands to the worker isolate, and |
| 473 /// vice versa. The returned future normally completes when the worker | 488 /// vice versa. The returned future normally completes when the worker |
| 474 /// isolate sends DriverCommand.ClosePort, or if the isolate is killed due to | 489 /// isolate sends DriverCommand.ClosePort, or if the isolate is killed due to |
| 475 /// DriverCommand.Signal arriving through client.commands. | 490 /// DriverCommand.Signal arriving through client.commands. |
| 476 Future<Null> attachClient(ClientController client) async { | 491 Future<Null> attachClient(ClientController client) async { |
| 492 crashReportRequested = false; |
| 477 errorSubscription.onData((errorList) { | 493 errorSubscription.onData((errorList) { |
| 478 String error = errorList[0]; | 494 String error = errorList[0]; |
| 479 String stackTrace = errorList[1]; | 495 String stackTrace = errorList[1]; |
| 496 if (!crashReportRequested) { |
| 497 client.printLineOnStderr(requestBugReportOnOtherCrashMessage); |
| 498 crashReportRequested = true; |
| 499 } |
| 480 client.printLineOnStderr(error); | 500 client.printLineOnStderr(error); |
| 481 if (stackTrace != null) { | 501 if (stackTrace != null) { |
| 482 client.printLineOnStderr(stackTrace); | 502 client.printLineOnStderr(stackTrace); |
| 483 } | 503 } |
| 484 workerReceivePort.close(); | 504 workerReceivePort.close(); |
| 485 }); | 505 }); |
| 486 errorSubscription.resume(); | 506 errorSubscription.resume(); |
| 487 handleCommand(Command command) { | 507 handleCommand(Command command) { |
| 488 if (command.code == DriverCommand.Signal && !eventLoopStarted) { | 508 if (command.code == DriverCommand.Signal && !eventLoopStarted) { |
| 489 isolate.kill(); | 509 isolate.kill(); |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 718 | 738 |
| 719 void error(error, StackTrace stackTrace) { | 739 void error(error, StackTrace stackTrace) { |
| 720 // TODO(ahe): Modify shutdown verb to report these errors. | 740 // TODO(ahe): Modify shutdown verb to report these errors. |
| 721 erroneousClients.add(this); | 741 erroneousClients.add(this); |
| 722 note("Crash (${arguments.join(' ')}).\n" | 742 note("Crash (${arguments.join(' ')}).\n" |
| 723 "${stringifyError(error, stackTrace)}"); | 743 "${stringifyError(error, stackTrace)}"); |
| 724 } | 744 } |
| 725 | 745 |
| 726 String toString() => "$id"; | 746 String toString() => "$id"; |
| 727 } | 747 } |
| OLD | NEW |