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 |