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 |