| OLD | NEW |
| 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 |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 169 class _ProcessStartStatus { | 169 class _ProcessStartStatus { |
| 170 int _errorCode; // Set to OS error code if process start failed. | 170 int _errorCode; // Set to OS error code if process start failed. |
| 171 String _errorMessage; // Set to OS error message if process start failed. | 171 String _errorMessage; // Set to OS error message if process start failed. |
| 172 } | 172 } |
| 173 | 173 |
| 174 | 174 |
| 175 // The NativeFieldWrapperClass1 can not be used with a mixin, due to missing | 175 // The NativeFieldWrapperClass1 can not be used with a mixin, due to missing |
| 176 // implicit constructor. | 176 // implicit constructor. |
| 177 class _ProcessImplNativeWrapper extends NativeFieldWrapperClass1 {} | 177 class _ProcessImplNativeWrapper extends NativeFieldWrapperClass1 {} |
| 178 | 178 |
| 179 class _ProcessImpl extends _ProcessImplNativeWrapper with _ServiceObject | 179 class _ProcessImpl extends _ProcessImplNativeWrapper implements Process { |
| 180 implements Process { | 180 _ProcessResourceInfo _resourceInfo; |
| 181 // Use default Map so we keep order. | 181 static bool connectedResourceHandler = false; |
| 182 static Map<int, _ProcessImpl> _processes = new Map<int, _ProcessImpl>(); | |
| 183 | 182 |
| 184 _ProcessImpl(String path, | 183 _ProcessImpl(String path, |
| 185 List<String> arguments, | 184 List<String> arguments, |
| 186 String this._workingDirectory, | 185 String this._workingDirectory, |
| 187 Map<String, String> environment, | 186 Map<String, String> environment, |
| 188 bool includeParentEnvironment, | 187 bool includeParentEnvironment, |
| 189 bool runInShell, | 188 bool runInShell, |
| 190 ProcessStartMode mode) : super() { | 189 ProcessStartMode mode) : super() { |
| 191 _processes[_serviceId] = this; | 190 if (!connectedResourceHandler) { |
| 191 registerExtension('__getStartedProcesses', |
| 192 _ProcessResourceInfo.getStartedProcesses); |
| 193 registerExtension('__getProcessById', |
| 194 _ProcessResourceInfo.getProcessInfoMapById); |
| 195 connectedResourceHandler = true; |
| 196 } |
| 197 |
| 192 if (runInShell) { | 198 if (runInShell) { |
| 193 arguments = _getShellArguments(path, arguments); | 199 arguments = _getShellArguments(path, arguments); |
| 194 path = _getShellCommand(); | 200 path = _getShellCommand(); |
| 195 } | 201 } |
| 196 | 202 |
| 197 if (path is !String) { | 203 if (path is !String) { |
| 198 throw new ArgumentError("Path is not a String: $path"); | 204 throw new ArgumentError("Path is not a String: $path"); |
| 199 } | 205 } |
| 200 _path = path; | 206 _path = path; |
| 201 | 207 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 _stderr = new _StdStream(new _Socket._readPipe()); | 266 _stderr = new _StdStream(new _Socket._readPipe()); |
| 261 _stderr._stream._owner = this; | 267 _stderr._stream._owner = this; |
| 262 } | 268 } |
| 263 if (mode == ProcessStartMode.NORMAL) { | 269 if (mode == ProcessStartMode.NORMAL) { |
| 264 _exitHandler = new _Socket._readPipe(); | 270 _exitHandler = new _Socket._readPipe(); |
| 265 } | 271 } |
| 266 _ended = false; | 272 _ended = false; |
| 267 _started = false; | 273 _started = false; |
| 268 } | 274 } |
| 269 | 275 |
| 270 String get _serviceTypePath => 'io/processes'; | |
| 271 String get _serviceTypeName => 'Process'; | |
| 272 | |
| 273 Map _toJSON(bool ref) { | |
| 274 var r = { | |
| 275 'id': _servicePath, | |
| 276 'type': _serviceType(ref), | |
| 277 'name': '$_path', | |
| 278 'user_name': '$_path', | |
| 279 'pid': '$pid', | |
| 280 'arguments': _arguments.join(' '), | |
| 281 }; | |
| 282 if (ref) { | |
| 283 return r; | |
| 284 } | |
| 285 r['started'] = _started; | |
| 286 r['ended'] = _ended; | |
| 287 r['path'] = _path; | |
| 288 r['environment'] = _environment; | |
| 289 r['workingDirectory'] = _workingDirectory == null ? '.' : _workingDirectory; | |
| 290 if (_stdin._sink._nativeSocket.owner != null) { | |
| 291 r['stdin'] = _stdin._sink._nativeSocket._toJSON(true); | |
| 292 } | |
| 293 if (_stdout._stream._nativeSocket.owner != null) { | |
| 294 r['stdout'] = _stdout._stream._nativeSocket._toJSON(true); | |
| 295 } | |
| 296 if (_stderr._stream._nativeSocket.owner != null) { | |
| 297 r['stderr'] = _stderr._stream._nativeSocket._toJSON(true); | |
| 298 } | |
| 299 return r; | |
| 300 } | |
| 301 | |
| 302 static String _getShellCommand() { | 276 static String _getShellCommand() { |
| 303 if (Platform.isWindows) { | 277 if (Platform.isWindows) { |
| 304 return 'cmd.exe'; | 278 return 'cmd.exe'; |
| 305 } | 279 } |
| 306 return '/bin/sh'; | 280 return '/bin/sh'; |
| 307 } | 281 } |
| 308 | 282 |
| 309 static List<String> _getShellArguments(String executable, | 283 static List<String> _getShellArguments(String executable, |
| 310 List<String> arguments) { | 284 List<String> arguments) { |
| 311 List<String> shellArguments = []; | 285 List<String> shellArguments = []; |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 411 if (!success) { | 385 if (!success) { |
| 412 completer.completeError( | 386 completer.completeError( |
| 413 new ProcessException(_path, | 387 new ProcessException(_path, |
| 414 _arguments, | 388 _arguments, |
| 415 status._errorMessage, | 389 status._errorMessage, |
| 416 status._errorCode)); | 390 status._errorCode)); |
| 417 return; | 391 return; |
| 418 } | 392 } |
| 419 | 393 |
| 420 _started = true; | 394 _started = true; |
| 395 _resourceInfo = new _ProcessResourceInfo(this); |
| 421 | 396 |
| 422 // Setup an exit handler to handle internal cleanup and possible | 397 // Setup an exit handler to handle internal cleanup and possible |
| 423 // callback when a process terminates. | 398 // callback when a process terminates. |
| 424 if (_mode == ProcessStartMode.NORMAL) { | 399 if (_mode == ProcessStartMode.NORMAL) { |
| 425 int exitDataRead = 0; | 400 int exitDataRead = 0; |
| 426 final int EXIT_DATA_SIZE = 8; | 401 final int EXIT_DATA_SIZE = 8; |
| 427 List<int> exitDataBuffer = new List<int>(EXIT_DATA_SIZE); | 402 List<int> exitDataBuffer = new List<int>(EXIT_DATA_SIZE); |
| 428 _exitHandler.listen((data) { | 403 _exitHandler.listen((data) { |
| 429 | 404 |
| 430 int exitCode(List<int> ints) { | 405 int exitCode(List<int> ints) { |
| 431 var code = _intFromBytes(ints, 0); | 406 var code = _intFromBytes(ints, 0); |
| 432 var negative = _intFromBytes(ints, 4); | 407 var negative = _intFromBytes(ints, 4); |
| 433 assert(negative == 0 || negative == 1); | 408 assert(negative == 0 || negative == 1); |
| 434 return (negative == 0) ? code : -code; | 409 return (negative == 0) ? code : -code; |
| 435 } | 410 } |
| 436 | 411 |
| 437 void handleExit() { | 412 void handleExit() { |
| 438 _ended = true; | 413 _ended = true; |
| 439 _exitCode.complete(exitCode(exitDataBuffer)); | 414 _exitCode.complete(exitCode(exitDataBuffer)); |
| 440 // Kill stdin, helping hand if the user forgot to do it. | 415 // Kill stdin, helping hand if the user forgot to do it. |
| 441 _stdin._sink.destroy(); | 416 _stdin._sink.destroy(); |
| 442 _processes.remove(_serviceId); | 417 _resourceInfo.stopped(); |
| 443 } | 418 } |
| 444 | 419 |
| 445 exitDataBuffer.setRange( | 420 exitDataBuffer.setRange( |
| 446 exitDataRead, exitDataRead + data.length, data); | 421 exitDataRead, exitDataRead + data.length, data); |
| 447 exitDataRead += data.length; | 422 exitDataRead += data.length; |
| 448 if (exitDataRead == EXIT_DATA_SIZE) { | 423 if (exitDataRead == EXIT_DATA_SIZE) { |
| 449 handleExit(); | 424 handleExit(); |
| 450 } | 425 } |
| 451 }); | 426 }); |
| 452 } | 427 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 470 _stderr._stream._nativeSocket, | 445 _stderr._stream._nativeSocket, |
| 471 _exitHandler._nativeSocket, | 446 _exitHandler._nativeSocket, |
| 472 status); | 447 status); |
| 473 if (!success) { | 448 if (!success) { |
| 474 throw new ProcessException(_path, | 449 throw new ProcessException(_path, |
| 475 _arguments, | 450 _arguments, |
| 476 status._errorMessage, | 451 status._errorMessage, |
| 477 status._errorCode); | 452 status._errorCode); |
| 478 } | 453 } |
| 479 | 454 |
| 455 _resourceInfo = new _ProcessResourceInfo(this); |
| 456 |
| 480 var result = _wait( | 457 var result = _wait( |
| 481 _stdin._sink._nativeSocket, | 458 _stdin._sink._nativeSocket, |
| 482 _stdout._stream._nativeSocket, | 459 _stdout._stream._nativeSocket, |
| 483 _stderr._stream._nativeSocket, | 460 _stderr._stream._nativeSocket, |
| 484 _exitHandler._nativeSocket); | 461 _exitHandler._nativeSocket); |
| 485 | 462 |
| 486 getOutput(output, encoding) { | 463 getOutput(output, encoding) { |
| 487 if (encoding == null) return output; | 464 if (encoding == null) return output; |
| 488 return encoding.decode(output); | 465 return encoding.decode(output); |
| 489 } | 466 } |
| 490 | 467 |
| 491 _processes.remove(_serviceId); | 468 _resourceInfo.stopped(); |
| 492 | 469 |
| 493 return new ProcessResult( | 470 return new ProcessResult( |
| 494 result[0], | 471 result[0], |
| 495 result[1], | 472 result[1], |
| 496 getOutput(result[2], stdoutEncoding), | 473 getOutput(result[2], stdoutEncoding), |
| 497 getOutput(result[3], stderrEncoding)); | 474 getOutput(result[3], stderrEncoding)); |
| 498 } | 475 } |
| 499 | 476 |
| 500 bool _startNative(String path, | 477 bool _startNative(String path, |
| 501 List<String> arguments, | 478 List<String> arguments, |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 618 Encoding stderrEncoding) { | 595 Encoding stderrEncoding) { |
| 619 var process = new _ProcessImpl(executable, | 596 var process = new _ProcessImpl(executable, |
| 620 arguments, | 597 arguments, |
| 621 workingDirectory, | 598 workingDirectory, |
| 622 environment, | 599 environment, |
| 623 includeParentEnvironment, | 600 includeParentEnvironment, |
| 624 runInShell, | 601 runInShell, |
| 625 ProcessStartMode.NORMAL); | 602 ProcessStartMode.NORMAL); |
| 626 return process._runAndWait(stdoutEncoding, stderrEncoding); | 603 return process._runAndWait(stdoutEncoding, stderrEncoding); |
| 627 } | 604 } |
| OLD | NEW |