| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 _ProcessImpl(String path, List<String> arguments, ProcessOptions options) { | 46 _ProcessImpl(String path, List<String> arguments, ProcessOptions options) { |
| 47 if (path is !String) { | 47 if (path is !String) { |
| 48 throw new ArgumentError("Path is not a String: $path"); | 48 throw new ArgumentError("Path is not a String: $path"); |
| 49 } | 49 } |
| 50 _path = path; | 50 _path = path; |
| 51 | 51 |
| 52 if (arguments is !List) { | 52 if (arguments is !List) { |
| 53 throw new ArgumentError("Arguments is not a List: $arguments"); | 53 throw new ArgumentError("Arguments is not a List: $arguments"); |
| 54 } | 54 } |
| 55 int len = arguments.length; | 55 int len = arguments.length; |
| 56 _arguments = new List<String>(len); | 56 _arguments = new List<String>.fixedLength(len); |
| 57 for (int i = 0; i < len; i++) { | 57 for (int i = 0; i < len; i++) { |
| 58 var arg = arguments[i]; | 58 var arg = arguments[i]; |
| 59 if (arg is !String) { | 59 if (arg is !String) { |
| 60 throw new ArgumentError("Non-string argument: $arg"); | 60 throw new ArgumentError("Non-string argument: $arg"); |
| 61 } | 61 } |
| 62 _arguments[i] = arguments[i]; | 62 _arguments[i] = arguments[i]; |
| 63 if (Platform.operatingSystem == 'windows') { | 63 if (Platform.operatingSystem == 'windows') { |
| 64 _arguments[i] = _windowsArgumentEscape(_arguments[i]); | 64 _arguments[i] = _windowsArgumentEscape(_arguments[i]); |
| 65 } | 65 } |
| 66 } | 66 } |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 _in, | 163 _in, |
| 164 _out, | 164 _out, |
| 165 _err, | 165 _err, |
| 166 _exitHandler, | 166 _exitHandler, |
| 167 status); | 167 status); |
| 168 if (!success) { | 168 if (!success) { |
| 169 _in.close(); | 169 _in.close(); |
| 170 _out.close(); | 170 _out.close(); |
| 171 _err.close(); | 171 _err.close(); |
| 172 _exitHandler.close(); | 172 _exitHandler.close(); |
| 173 completer.completeException( | 173 completer.completeError( |
| 174 new ProcessException(_path, | 174 new ProcessException(_path, |
| 175 _arguments, | 175 _arguments, |
| 176 status._errorMessage, | 176 status._errorMessage, |
| 177 status._errorCode)); | 177 status._errorCode)); |
| 178 return; | 178 return; |
| 179 } | 179 } |
| 180 _started = true; | 180 _started = true; |
| 181 | 181 |
| 182 _in._closed = false; | 182 _in._closed = false; |
| 183 _out._closed = false; | 183 _out._closed = false; |
| 184 _err._closed = false; | 184 _err._closed = false; |
| 185 _exitHandler._closed = false; | 185 _exitHandler._closed = false; |
| 186 | 186 |
| 187 // Make sure to activate socket handlers now that the file | 187 // Make sure to activate socket handlers now that the file |
| 188 // descriptors have been set. | 188 // descriptors have been set. |
| 189 _in._activateHandlers(); | 189 _in._activateHandlers(); |
| 190 _out._activateHandlers(); | 190 _out._activateHandlers(); |
| 191 _err._activateHandlers(); | 191 _err._activateHandlers(); |
| 192 | 192 |
| 193 // Setup an exit handler to handle internal cleanup and possible | 193 // Setup an exit handler to handle internal cleanup and possible |
| 194 // callback when a process terminates. | 194 // callback when a process terminates. |
| 195 int exitDataRead = 0; | 195 int exitDataRead = 0; |
| 196 final int EXIT_DATA_SIZE = 8; | 196 final int EXIT_DATA_SIZE = 8; |
| 197 List<int> exitDataBuffer = new List<int>(EXIT_DATA_SIZE); | 197 List<int> exitDataBuffer = new List<int>.fixedLength(EXIT_DATA_SIZE); |
| 198 _exitHandler.inputStream.onData = () { | 198 _exitHandler.inputStream.onData = () { |
| 199 | 199 |
| 200 int exitCode(List<int> ints) { | 200 int exitCode(List<int> ints) { |
| 201 var code = _intFromBytes(ints, 0); | 201 var code = _intFromBytes(ints, 0); |
| 202 var negative = _intFromBytes(ints, 4); | 202 var negative = _intFromBytes(ints, 4); |
| 203 assert(negative == 0 || negative == 1); | 203 assert(negative == 0 || negative == 1); |
| 204 return (negative == 0) ? code : -code; | 204 return (negative == 0) ? code : -code; |
| 205 } | 205 } |
| 206 | 206 |
| 207 void handleExit() { | 207 void handleExit() { |
| 208 _ended = true; | 208 _ended = true; |
| 209 if (_onExit != null) { | 209 _exitCode = exitCode(exitDataBuffer); |
| 210 _onExit(exitCode(exitDataBuffer)); | 210 if (_onExit != null) _onExit(_exitCode); |
| 211 } | |
| 212 _out.close(); | 211 _out.close(); |
| 213 } | 212 } |
| 214 | 213 |
| 215 exitDataRead += _exitHandler.inputStream.readInto( | 214 exitDataRead += _exitHandler.inputStream.readInto( |
| 216 exitDataBuffer, exitDataRead, EXIT_DATA_SIZE - exitDataRead); | 215 exitDataBuffer, exitDataRead, EXIT_DATA_SIZE - exitDataRead); |
| 217 if (exitDataRead == EXIT_DATA_SIZE) { | 216 if (exitDataRead == EXIT_DATA_SIZE) { |
| 218 _exitHandler.close(); | 217 _exitHandler.close(); |
| 219 handleExit(); | 218 handleExit(); |
| 220 } | 219 } |
| 221 }; | 220 }; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 250 bool kill([ProcessSignal signal = ProcessSignal.SIGTERM]) { | 249 bool kill([ProcessSignal signal = ProcessSignal.SIGTERM]) { |
| 251 if (signal is! ProcessSignal) { | 250 if (signal is! ProcessSignal) { |
| 252 throw new ArgumentError( | 251 throw new ArgumentError( |
| 253 "Argument 'signal' must be a ProcessSignal"); | 252 "Argument 'signal' must be a ProcessSignal"); |
| 254 } | 253 } |
| 255 assert(_started); | 254 assert(_started); |
| 256 if (_ended) return false; | 255 if (_ended) return false; |
| 257 return _kill(this, signal._signalNumber); | 256 return _kill(this, signal._signalNumber); |
| 258 } | 257 } |
| 259 | 258 |
| 259 void add(List<int> data) { |
| 260 stdin.write(data); |
| 261 } |
| 262 |
| 263 void close() { |
| 264 stdin.close(); |
| 265 } |
| 266 |
| 267 void signalError(ASyncError error) { |
| 268 // TODO(ajohnsen): close? |
| 269 } |
| 270 |
| 271 Stream<List<int>> get stdoutStream |
| 272 => new _InputStreamController(stdout).stream; |
| 273 |
| 274 Stream<List<int>> get stderrStream |
| 275 => new _InputStreamController(stderr).stream; |
| 276 |
| 260 bool _kill(Process p, int signal) native "Process_Kill"; | 277 bool _kill(Process p, int signal) native "Process_Kill"; |
| 261 | 278 |
| 262 void set onExit(void callback(int exitCode)) { | 279 void set onExit(void callback(int exitCode)) { |
| 263 if (_ended) { | 280 if (_ended) callback(_exitCode); |
| 264 throw new ProcessException(_path, _arguments, "Process killed"); | |
| 265 } | |
| 266 _onExit = callback; | 281 _onExit = callback; |
| 267 } | 282 } |
| 268 | 283 |
| 269 String _path; | 284 String _path; |
| 270 List<String> _arguments; | 285 List<String> _arguments; |
| 271 String _workingDirectory; | 286 String _workingDirectory; |
| 272 List<String> _environment; | 287 List<String> _environment; |
| 273 // Private methods of _Socket are used by _in, _out, and _err. | 288 // Private methods of _Socket are used by _in, _out, and _err. |
| 274 _Socket _in; | 289 _Socket _in; |
| 275 _Socket _out; | 290 _Socket _out; |
| 276 _Socket _err; | 291 _Socket _err; |
| 277 Socket _exitHandler; | 292 Socket _exitHandler; |
| 293 int _exitCode; |
| 278 bool _ended; | 294 bool _ended; |
| 279 bool _started; | 295 bool _started; |
| 280 Function _onExit; | 296 Function _onExit; |
| 281 } | 297 } |
| 282 | 298 |
| 283 | 299 |
| 284 // _NonInteractiveProcess is a wrapper around an interactive process | 300 // _NonInteractiveProcess is a wrapper around an interactive process |
| 285 // that buffers output so it can be delivered when the process exits. | 301 // that buffers output so it can be delivered when the process exits. |
| 286 // _NonInteractiveProcess is used to implement the Process.run | 302 // _NonInteractiveProcess is used to implement the Process.run |
| 287 // method. | 303 // method. |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 _stderrBuffer = new StringBuffer(); | 355 _stderrBuffer = new StringBuffer(); |
| 340 var stderrStream = new StringInputStream(p.stderr, stderrEncoding); | 356 var stderrStream = new StringInputStream(p.stderr, stderrEncoding); |
| 341 stderrStream.onData = () { | 357 stderrStream.onData = () { |
| 342 var data = stderrStream.read(); | 358 var data = stderrStream.read(); |
| 343 if (data != null) _stderrBuffer.add(data); | 359 if (data != null) _stderrBuffer.add(data); |
| 344 }; | 360 }; |
| 345 stderrStream.onClosed = () { | 361 stderrStream.onClosed = () { |
| 346 _stderrClosed = true; | 362 _stderrClosed = true; |
| 347 _checkDone(); | 363 _checkDone(); |
| 348 }; | 364 }; |
| 349 }); | 365 }).catchError((error) { |
| 350 | 366 _completer.completeError(error.error); |
| 351 processFuture.handleException((error) { | |
| 352 _completer.completeException(error); | |
| 353 return true; | |
| 354 }); | 367 }); |
| 355 } | 368 } |
| 356 | 369 |
| 357 void _checkDone() { | 370 void _checkDone() { |
| 358 if (_exitCode != null && _stderrClosed && _stdoutClosed) { | 371 if (_exitCode != null && _stderrClosed && _stdoutClosed) { |
| 359 _completer.complete(new _ProcessResult(_exitCode, | 372 _completer.complete(new _ProcessResult(_exitCode, |
| 360 _stdoutBuffer.toString(), | 373 _stdoutBuffer.toString(), |
| 361 _stderrBuffer.toString())); | 374 _stderrBuffer.toString())); |
| 362 } | 375 } |
| 363 } | 376 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 375 | 388 |
| 376 class _ProcessResult implements ProcessResult { | 389 class _ProcessResult implements ProcessResult { |
| 377 const _ProcessResult(int this.exitCode, | 390 const _ProcessResult(int this.exitCode, |
| 378 String this.stdout, | 391 String this.stdout, |
| 379 String this.stderr); | 392 String this.stderr); |
| 380 | 393 |
| 381 final int exitCode; | 394 final int exitCode; |
| 382 final String stdout; | 395 final String stdout; |
| 383 final String stderr; | 396 final String stderr; |
| 384 } | 397 } |
| OLD | NEW |