Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: runtime/bin/process_patch.dart

Issue 890633002: Add an option for starting a detached process with stdio connected (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/bin/process_macos.cc ('k') | runtime/bin/process_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart 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 file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 patch class _WindowsCodePageDecoder { 5 patch class _WindowsCodePageDecoder {
6 /* patch */ static String _decodeBytes(List<int> bytes) 6 /* patch */ static String _decodeBytes(List<int> bytes)
7 native "SystemEncodingToString"; 7 native "SystemEncodingToString";
8 } 8 }
9 9
10 10
11 patch class _WindowsCodePageEncoder { 11 patch class _WindowsCodePageEncoder {
12 /* patch */ static List<int> _encodeString(String string) 12 /* patch */ static List<int> _encodeString(String string)
13 native "StringToSystemEncoding"; 13 native "StringToSystemEncoding";
14 } 14 }
15 15
16 16
17 patch class Process { 17 patch class Process {
18 /* patch */ static Future<Process> start( 18 /* patch */ static Future<Process> start(
19 String executable, 19 String executable,
20 List<String> arguments, 20 List<String> arguments,
21 {String workingDirectory, 21 {String workingDirectory,
22 Map<String, String> environment, 22 Map<String, String> environment,
23 bool includeParentEnvironment: true, 23 bool includeParentEnvironment: true,
24 bool runInShell: false, 24 bool runInShell: false,
25 bool detach: false}) { 25 ProcessStartMode mode: ProcessStartMode.NORMAL}) {
26 _ProcessImpl process = new _ProcessImpl(executable, 26 _ProcessImpl process = new _ProcessImpl(executable,
27 arguments, 27 arguments,
28 workingDirectory, 28 workingDirectory,
29 environment, 29 environment,
30 includeParentEnvironment, 30 includeParentEnvironment,
31 runInShell, 31 runInShell,
32 detach); 32 mode);
33 return process._start(); 33 return process._start();
34 } 34 }
35 35
36 /* patch */ static Future<ProcessResult> run( 36 /* patch */ static Future<ProcessResult> run(
37 String executable, 37 String executable,
38 List<String> arguments, 38 List<String> arguments,
39 {String workingDirectory, 39 {String workingDirectory,
40 Map<String, String> environment, 40 Map<String, String> environment,
41 bool includeParentEnvironment: true, 41 bool includeParentEnvironment: true,
42 bool runInShell: false, 42 bool runInShell: false,
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 implements Process { 169 implements Process {
170 // Use default Map so we keep order. 170 // Use default Map so we keep order.
171 static Map<int, _ProcessImpl> _processes = new Map<int, _ProcessImpl>(); 171 static Map<int, _ProcessImpl> _processes = new Map<int, _ProcessImpl>();
172 172
173 _ProcessImpl(String path, 173 _ProcessImpl(String path,
174 List<String> arguments, 174 List<String> arguments,
175 String this._workingDirectory, 175 String this._workingDirectory,
176 Map<String, String> environment, 176 Map<String, String> environment,
177 bool includeParentEnvironment, 177 bool includeParentEnvironment,
178 bool runInShell, 178 bool runInShell,
179 bool detach) : super() { 179 ProcessStartMode mode) : super() {
180 _processes[_serviceId] = this; 180 _processes[_serviceId] = this;
181 if (runInShell) { 181 if (runInShell) {
182 arguments = _getShellArguments(path, arguments); 182 arguments = _getShellArguments(path, arguments);
183 path = _getShellCommand(); 183 path = _getShellCommand();
184 } 184 }
185 185
186 if (path is !String) { 186 if (path is !String) {
187 throw new ArgumentError("Path is not a String: $path"); 187 throw new ArgumentError("Path is not a String: $path");
188 } 188 }
189 _path = path; 189 _path = path;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 Platform.environment.forEach((key, value) { 226 Platform.environment.forEach((key, value) {
227 assert(key is String); 227 assert(key is String);
228 assert(value is String); 228 assert(value is String);
229 // Do not override keys already set as part of environment. 229 // Do not override keys already set as part of environment.
230 if (!environment.containsKey(key)) { 230 if (!environment.containsKey(key)) {
231 _environment.add('$key=$value'); 231 _environment.add('$key=$value');
232 } 232 }
233 }); 233 });
234 } 234 }
235 235
236 if (detach is !bool) { 236 if (mode is !ProcessStartMode) {
237 throw new ArgumentError("Detach is not a boolean: $detach"); 237 throw new ArgumentError("Mode is not a ProcessStartMode: $mode");
238 } 238 }
239 _detach = detach; 239 _mode = mode;
240 240
241 241 if (mode != ProcessStartMode.DETACHED) {
242 if (!detach) {
243 // stdin going to process. 242 // stdin going to process.
244 _stdin = new _StdSink(new _Socket._writePipe()); 243 _stdin = new _StdSink(new _Socket._writePipe());
245 _stdin._sink._owner = this; 244 _stdin._sink._owner = this;
246 // stdout coming from process. 245 // stdout coming from process.
247 _stdout = new _StdStream(new _Socket._readPipe()); 246 _stdout = new _StdStream(new _Socket._readPipe());
248 _stdout._stream._owner = this; 247 _stdout._stream._owner = this;
249 // stderr coming from process. 248 // stderr coming from process.
250 _stderr = new _StdStream(new _Socket._readPipe()); 249 _stderr = new _StdStream(new _Socket._readPipe());
251 _stderr._stream._owner = this; 250 _stderr._stream._owner = this;
251 }
252 if (mode == ProcessStartMode.NORMAL) {
252 _exitHandler = new _Socket._readPipe(); 253 _exitHandler = new _Socket._readPipe();
253 } 254 }
254 _ended = false; 255 _ended = false;
255 _started = false; 256 _started = false;
256 } 257 }
257 258
258 String get _serviceTypePath => 'io/processes'; 259 String get _serviceTypePath => 'io/processes';
259 String get _serviceTypeName => 'Process'; 260 String get _serviceTypeName => 'Process';
260 261
261 Map _toJSON(bool ref) { 262 Map _toJSON(bool ref) {
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 368
368 int _intFromBytes(List<int> bytes, int offset) { 369 int _intFromBytes(List<int> bytes, int offset) {
369 return (bytes[offset] + 370 return (bytes[offset] +
370 (bytes[offset + 1] << 8) + 371 (bytes[offset + 1] << 8) +
371 (bytes[offset + 2] << 16) + 372 (bytes[offset + 2] << 16) +
372 (bytes[offset + 3] << 24)); 373 (bytes[offset + 3] << 24));
373 } 374 }
374 375
375 Future<Process> _start() { 376 Future<Process> _start() {
376 var completer = new Completer(); 377 var completer = new Completer();
377 if (!_detach) { 378 if (_mode == ProcessStartMode.NORMAL) {
378 _exitCode = new Completer<int>(); 379 _exitCode = new Completer<int>();
379 } 380 }
380 // TODO(ager): Make the actual process starting really async instead of 381 // TODO(ager): Make the actual process starting really async instead of
381 // simulating it with a timer. 382 // simulating it with a timer.
382 Timer.run(() { 383 Timer.run(() {
383 var status = new _ProcessStartStatus(); 384 var status = new _ProcessStartStatus();
384 bool success = 385 bool success =
385 _startNative(_path, 386 _startNative(_path,
386 _arguments, 387 _arguments,
387 _workingDirectory, 388 _workingDirectory,
388 _environment, 389 _environment,
389 _detach, 390 _mode.index,
390 _detach ? null : _stdin._sink._nativeSocket, 391 _mode == ProcessStartMode.DETACHED
391 _detach ? null : _stdout._stream._nativeSocket, 392 ? null : _stdin._sink._nativeSocket,
392 _detach ? null : _stderr._stream._nativeSocket, 393 _mode == ProcessStartMode.DETACHED
393 _detach ? null : _exitHandler._nativeSocket, 394 ? null : _stdout._stream._nativeSocket,
395 _mode == ProcessStartMode.DETACHED
396 ? null : _stderr._stream._nativeSocket,
397 _mode != ProcessStartMode.NORMAL
398 ? null : _exitHandler._nativeSocket,
394 status); 399 status);
395 if (!success) { 400 if (!success) {
396 completer.completeError( 401 completer.completeError(
397 new ProcessException(_path, 402 new ProcessException(_path,
398 _arguments, 403 _arguments,
399 status._errorMessage, 404 status._errorMessage,
400 status._errorCode)); 405 status._errorCode));
401 return; 406 return;
402 } 407 }
403 408
404 _started = true; 409 _started = true;
405 410
406 // Setup an exit handler to handle internal cleanup and possible 411 // Setup an exit handler to handle internal cleanup and possible
407 // callback when a process terminates. 412 // callback when a process terminates.
408 if (!_detach) { 413 if (_mode == ProcessStartMode.NORMAL) {
409 int exitDataRead = 0; 414 int exitDataRead = 0;
410 final int EXIT_DATA_SIZE = 8; 415 final int EXIT_DATA_SIZE = 8;
411 List<int> exitDataBuffer = new List<int>(EXIT_DATA_SIZE); 416 List<int> exitDataBuffer = new List<int>(EXIT_DATA_SIZE);
412 _exitHandler.listen((data) { 417 _exitHandler.listen((data) {
413 418
414 int exitCode(List<int> ints) { 419 int exitCode(List<int> ints) {
415 var code = _intFromBytes(ints, 0); 420 var code = _intFromBytes(ints, 0);
416 var negative = _intFromBytes(ints, 4); 421 var negative = _intFromBytes(ints, 4);
417 assert(negative == 0 || negative == 1); 422 assert(negative == 0 || negative == 1);
418 return (negative == 0) ? code : -code; 423 return (negative == 0) ? code : -code;
(...skipping 22 matching lines...) Expand all
441 } 446 }
442 447
443 ProcessResult _runAndWait(Encoding stdoutEncoding, 448 ProcessResult _runAndWait(Encoding stdoutEncoding,
444 Encoding stderrEncoding) { 449 Encoding stderrEncoding) {
445 var status = new _ProcessStartStatus(); 450 var status = new _ProcessStartStatus();
446 _exitCode = new Completer<int>(); 451 _exitCode = new Completer<int>();
447 bool success = _startNative(_path, 452 bool success = _startNative(_path,
448 _arguments, 453 _arguments,
449 _workingDirectory, 454 _workingDirectory,
450 _environment, 455 _environment,
451 false, 456 ProcessStartMode.NORMAL.index,
452 _stdin._sink._nativeSocket, 457 _stdin._sink._nativeSocket,
453 _stdout._stream._nativeSocket, 458 _stdout._stream._nativeSocket,
454 _stderr._stream._nativeSocket, 459 _stderr._stream._nativeSocket,
455 _exitHandler._nativeSocket, 460 _exitHandler._nativeSocket,
456 status); 461 status);
457 if (!success) { 462 if (!success) {
458 throw new ProcessException(_path, 463 throw new ProcessException(_path,
459 _arguments, 464 _arguments,
460 status._errorMessage, 465 status._errorMessage,
461 status._errorCode); 466 status._errorCode);
(...skipping 16 matching lines...) Expand all
478 result[0], 483 result[0],
479 result[1], 484 result[1],
480 getOutput(result[2], stdoutEncoding), 485 getOutput(result[2], stdoutEncoding),
481 getOutput(result[3], stderrEncoding)); 486 getOutput(result[3], stderrEncoding));
482 } 487 }
483 488
484 bool _startNative(String path, 489 bool _startNative(String path,
485 List<String> arguments, 490 List<String> arguments,
486 String workingDirectory, 491 String workingDirectory,
487 List<String> environment, 492 List<String> environment,
488 bool detach, 493 int mode,
489 _NativeSocket stdin, 494 _NativeSocket stdin,
490 _NativeSocket stdout, 495 _NativeSocket stdout,
491 _NativeSocket stderr, 496 _NativeSocket stderr,
492 _NativeSocket exitHandler, 497 _NativeSocket exitHandler,
493 _ProcessStartStatus status) native "Process_Start"; 498 _ProcessStartStatus status) native "Process_Start";
494 499
495 _wait(_NativeSocket stdin, 500 _wait(_NativeSocket stdin,
496 _NativeSocket stdout, 501 _NativeSocket stdout,
497 _NativeSocket stderr, 502 _NativeSocket stderr,
498 _NativeSocket exitHandler) native "Process_Wait"; 503 _NativeSocket exitHandler) native "Process_Wait";
(...skipping 23 matching lines...) Expand all
522 } 527 }
523 528
524 bool _kill(Process p, int signal) native "Process_Kill"; 529 bool _kill(Process p, int signal) native "Process_Kill";
525 530
526 int get pid => _ProcessUtils._pid(this); 531 int get pid => _ProcessUtils._pid(this);
527 532
528 String _path; 533 String _path;
529 List<String> _arguments; 534 List<String> _arguments;
530 String _workingDirectory; 535 String _workingDirectory;
531 List<String> _environment; 536 List<String> _environment;
532 bool _detach; 537 ProcessStartMode _mode;
533 // Private methods of Socket are used by _in, _out, and _err. 538 // Private methods of Socket are used by _in, _out, and _err.
534 _StdSink _stdin; 539 _StdSink _stdin;
535 _StdStream _stdout; 540 _StdStream _stdout;
536 _StdStream _stderr; 541 _StdStream _stderr;
537 Socket _exitHandler; 542 Socket _exitHandler;
538 bool _ended; 543 bool _ended;
539 bool _started; 544 bool _started;
540 Completer<int> _exitCode; 545 Completer<int> _exitCode;
541 } 546 }
542 547
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 bool includeParentEnvironment, 606 bool includeParentEnvironment,
602 bool runInShell, 607 bool runInShell,
603 Encoding stdoutEncoding, 608 Encoding stdoutEncoding,
604 Encoding stderrEncoding) { 609 Encoding stderrEncoding) {
605 var process = new _ProcessImpl(executable, 610 var process = new _ProcessImpl(executable,
606 arguments, 611 arguments,
607 workingDirectory, 612 workingDirectory,
608 environment, 613 environment,
609 includeParentEnvironment, 614 includeParentEnvironment,
610 runInShell, 615 runInShell,
611 false); 616 ProcessStartMode.NORMAL);
612 return process._runAndWait(stdoutEncoding, stderrEncoding); 617 return process._runAndWait(stdoutEncoding, stderrEncoding);
613 } 618 }
614 619
615 620
616 class _ProcessResult implements ProcessResult { 621 class _ProcessResult implements ProcessResult {
617 const _ProcessResult(int this.pid, 622 const _ProcessResult(int this.pid,
618 int this.exitCode, 623 int this.exitCode,
619 this.stdout, 624 this.stdout,
620 this.stderr); 625 this.stderr);
621 626
622 final int pid; 627 final int pid;
623 final int exitCode; 628 final int exitCode;
624 final stdout; 629 final stdout;
625 final stderr; 630 final stderr;
626 } 631 }
OLDNEW
« no previous file with comments | « runtime/bin/process_macos.cc ('k') | runtime/bin/process_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698