| 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 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 } | 150 } |
| 151 } | 151 } |
| 152 | 152 |
| 153 | 153 |
| 154 class _ProcessStartStatus { | 154 class _ProcessStartStatus { |
| 155 int _errorCode; // Set to OS error code if process start failed. | 155 int _errorCode; // Set to OS error code if process start failed. |
| 156 String _errorMessage; // Set to OS error message if process start failed. | 156 String _errorMessage; // Set to OS error message if process start failed. |
| 157 } | 157 } |
| 158 | 158 |
| 159 | 159 |
| 160 class _ProcessImpl extends NativeFieldWrapperClass1 implements Process { | 160 // The NativeFieldWrapperClass1 can not be used with a mixin, due to missing |
| 161 // implicit constructor. |
| 162 class _ProcessImplNativeWrapper extends NativeFieldWrapperClass1 {} |
| 163 |
| 164 class _ProcessImpl extends _ProcessImplNativeWrapper with _ServiceObject |
| 165 implements Process { |
| 166 // Use default Map so we keep order. |
| 167 static Map<int, _ProcessImpl> _processes = new Map<int, _ProcessImpl>(); |
| 168 |
| 161 _ProcessImpl(String path, | 169 _ProcessImpl(String path, |
| 162 List<String> arguments, | 170 List<String> arguments, |
| 163 String this._workingDirectory, | 171 String this._workingDirectory, |
| 164 Map<String, String> environment, | 172 Map<String, String> environment, |
| 165 bool includeParentEnvironment, | 173 bool includeParentEnvironment, |
| 166 bool runInShell) { | 174 bool runInShell) : super() { |
| 175 _processes[_serviceId] = this; |
| 167 if (runInShell) { | 176 if (runInShell) { |
| 168 arguments = _getShellArguments(path, arguments); | 177 arguments = _getShellArguments(path, arguments); |
| 169 path = _getShellCommand(); | 178 path = _getShellCommand(); |
| 170 } | 179 } |
| 171 | 180 |
| 172 if (path is !String) { | 181 if (path is !String) { |
| 173 throw new ArgumentError("Path is not a String: $path"); | 182 throw new ArgumentError("Path is not a String: $path"); |
| 174 } | 183 } |
| 175 _path = path; | 184 _path = path; |
| 176 | 185 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 _stdin = new _StdSink(new _Socket._writePipe()); | 232 _stdin = new _StdSink(new _Socket._writePipe()); |
| 224 // stdout coming from process. | 233 // stdout coming from process. |
| 225 _stdout = new _StdStream(new _Socket._readPipe()); | 234 _stdout = new _StdStream(new _Socket._readPipe()); |
| 226 // stderr coming from process. | 235 // stderr coming from process. |
| 227 _stderr = new _StdStream(new _Socket._readPipe()); | 236 _stderr = new _StdStream(new _Socket._readPipe()); |
| 228 _exitHandler = new _Socket._readPipe(); | 237 _exitHandler = new _Socket._readPipe(); |
| 229 _ended = false; | 238 _ended = false; |
| 230 _started = false; | 239 _started = false; |
| 231 } | 240 } |
| 232 | 241 |
| 242 String get _serviceTypePath => 'io/processes'; |
| 243 String get _serviceTypeName => 'Process'; |
| 244 |
| 245 Map _toJSON(bool ref) { |
| 246 var r = { |
| 247 'id': _servicePath, |
| 248 'type': _serviceType(ref), |
| 249 'name': '$_path', |
| 250 'user_name': '$_path', |
| 251 'pid': '$pid', |
| 252 'arguments': _arguments.join(' '), |
| 253 }; |
| 254 if (ref) { |
| 255 return r; |
| 256 } |
| 257 r['started'] = _started; |
| 258 r['ended'] = _ended; |
| 259 r['path'] = _path; |
| 260 r['environment'] = _environment; |
| 261 r['workingDirectory'] = _workingDirectory == null ? '.' : _workingDirectory; |
| 262 return r; |
| 263 } |
| 264 |
| 233 static String _getShellCommand() { | 265 static String _getShellCommand() { |
| 234 if (Platform.isWindows) { | 266 if (Platform.isWindows) { |
| 235 return 'cmd.exe'; | 267 return 'cmd.exe'; |
| 236 } | 268 } |
| 237 return '/bin/sh'; | 269 return '/bin/sh'; |
| 238 } | 270 } |
| 239 | 271 |
| 240 static List<String> _getShellArguments(String executable, | 272 static List<String> _getShellArguments(String executable, |
| 241 List<String> arguments) { | 273 List<String> arguments) { |
| 242 List<String> shellArguments = []; | 274 List<String> shellArguments = []; |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 _exitHandler._nativeSocket, | 363 _exitHandler._nativeSocket, |
| 332 status); | 364 status); |
| 333 if (!success) { | 365 if (!success) { |
| 334 completer.completeError( | 366 completer.completeError( |
| 335 new ProcessException(_path, | 367 new ProcessException(_path, |
| 336 _arguments, | 368 _arguments, |
| 337 status._errorMessage, | 369 status._errorMessage, |
| 338 status._errorCode)); | 370 status._errorCode)); |
| 339 return; | 371 return; |
| 340 } | 372 } |
| 341 // Reset values which are no longer needed. | |
| 342 _path = null; | |
| 343 _arguments = null; | |
| 344 _workingDirectory = null; | |
| 345 _environment = null; | |
| 346 | 373 |
| 347 _started = true; | 374 _started = true; |
| 348 | 375 |
| 349 // Setup an exit handler to handle internal cleanup and possible | 376 // Setup an exit handler to handle internal cleanup and possible |
| 350 // callback when a process terminates. | 377 // callback when a process terminates. |
| 351 int exitDataRead = 0; | 378 int exitDataRead = 0; |
| 352 final int EXIT_DATA_SIZE = 8; | 379 final int EXIT_DATA_SIZE = 8; |
| 353 List<int> exitDataBuffer = new List<int>(EXIT_DATA_SIZE); | 380 List<int> exitDataBuffer = new List<int>(EXIT_DATA_SIZE); |
| 354 _exitHandler.listen((data) { | 381 _exitHandler.listen((data) { |
| 355 | 382 |
| 356 int exitCode(List<int> ints) { | 383 int exitCode(List<int> ints) { |
| 357 var code = _intFromBytes(ints, 0); | 384 var code = _intFromBytes(ints, 0); |
| 358 var negative = _intFromBytes(ints, 4); | 385 var negative = _intFromBytes(ints, 4); |
| 359 assert(negative == 0 || negative == 1); | 386 assert(negative == 0 || negative == 1); |
| 360 return (negative == 0) ? code : -code; | 387 return (negative == 0) ? code : -code; |
| 361 } | 388 } |
| 362 | 389 |
| 363 void handleExit() { | 390 void handleExit() { |
| 364 _ended = true; | 391 _ended = true; |
| 365 _exitCode.complete(exitCode(exitDataBuffer)); | 392 _exitCode.complete(exitCode(exitDataBuffer)); |
| 366 // Kill stdin, helping hand if the user forgot to do it. | 393 // Kill stdin, helping hand if the user forgot to do it. |
| 367 _stdin._sink.destroy(); | 394 _stdin._sink.destroy(); |
| 395 _processes.remove(_serviceId); |
| 368 } | 396 } |
| 369 | 397 |
| 370 exitDataBuffer.setRange(exitDataRead, exitDataRead + data.length, data); | 398 exitDataBuffer.setRange(exitDataRead, exitDataRead + data.length, data); |
| 371 exitDataRead += data.length; | 399 exitDataRead += data.length; |
| 372 if (exitDataRead == EXIT_DATA_SIZE) { | 400 if (exitDataRead == EXIT_DATA_SIZE) { |
| 373 handleExit(); | 401 handleExit(); |
| 374 } | 402 } |
| 375 }); | 403 }); |
| 376 | 404 |
| 377 completer.complete(this); | 405 completer.complete(this); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 390 _stdout._stream._nativeSocket, | 418 _stdout._stream._nativeSocket, |
| 391 _stderr._stream._nativeSocket, | 419 _stderr._stream._nativeSocket, |
| 392 _exitHandler._nativeSocket, | 420 _exitHandler._nativeSocket, |
| 393 status); | 421 status); |
| 394 if (!success) { | 422 if (!success) { |
| 395 throw new ProcessException(_path, | 423 throw new ProcessException(_path, |
| 396 _arguments, | 424 _arguments, |
| 397 status._errorMessage, | 425 status._errorMessage, |
| 398 status._errorCode); | 426 status._errorCode); |
| 399 } | 427 } |
| 400 // Reset values which are no longer needed. | |
| 401 _path = null; | |
| 402 _arguments = null; | |
| 403 _workingDirectory = null; | |
| 404 _environment = null; | |
| 405 | 428 |
| 406 var result = _wait( | 429 var result = _wait( |
| 407 _stdin._sink._nativeSocket, | 430 _stdin._sink._nativeSocket, |
| 408 _stdout._stream._nativeSocket, | 431 _stdout._stream._nativeSocket, |
| 409 _stderr._stream._nativeSocket, | 432 _stderr._stream._nativeSocket, |
| 410 _exitHandler._nativeSocket); | 433 _exitHandler._nativeSocket); |
| 411 | 434 |
| 412 getOutput(output, encoding) { | 435 getOutput(output, encoding) { |
| 413 if (encoding == null) return output; | 436 if (encoding == null) return output; |
| 414 return encoding.decode(output); | 437 return encoding.decode(output); |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 554 const _ProcessResult(int this.pid, | 577 const _ProcessResult(int this.pid, |
| 555 int this.exitCode, | 578 int this.exitCode, |
| 556 this.stdout, | 579 this.stdout, |
| 557 this.stderr); | 580 this.stderr); |
| 558 | 581 |
| 559 final int pid; | 582 final int pid; |
| 560 final int exitCode; | 583 final int exitCode; |
| 561 final stdout; | 584 final stdout; |
| 562 final stderr; | 585 final stderr; |
| 563 } | 586 } |
| OLD | NEW |