| 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 _exit(int status) native "Exit"; | 5 _exit(int status) native "Exit"; |
| 6 | 6 |
| 7 class _ProcessStartStatus { | 7 class _ProcessStartStatus { |
| 8 int _errorCode; // Set to OS error code if process start failed. | 8 int _errorCode; // Set to OS error code if process start failed. |
| 9 String _errorMessage; // Set to OS error message if process start failed. | 9 String _errorMessage; // Set to OS error message if process start failed. |
| 10 } | 10 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 "Environment key or value is not a string: ($key, $value)"); | 66 "Environment key or value is not a string: ($key, $value)"); |
| 67 } | 67 } |
| 68 _environment.add('$key=$value'); | 68 _environment.add('$key=$value'); |
| 69 }); | 69 }); |
| 70 } | 70 } |
| 71 | 71 |
| 72 _in = new _Socket._internalReadOnly(); // stdout coming from process. | 72 _in = new _Socket._internalReadOnly(); // stdout coming from process. |
| 73 _out = new _Socket._internalWriteOnly(); // stdin going to process. | 73 _out = new _Socket._internalWriteOnly(); // stdin going to process. |
| 74 _err = new _Socket._internalReadOnly(); // stderr coming from process. | 74 _err = new _Socket._internalReadOnly(); // stderr coming from process. |
| 75 _exitHandler = new _Socket._internalReadOnly(); | 75 _exitHandler = new _Socket._internalReadOnly(); |
| 76 _closed = false; | |
| 77 _ended = false; | 76 _ended = false; |
| 78 _started = false; | 77 _started = false; |
| 79 _onExit = null; | 78 _onExit = null; |
| 80 } | 79 } |
| 81 | 80 |
| 82 String _windowsArgumentEscape(String argument) { | 81 String _windowsArgumentEscape(String argument) { |
| 83 var result = argument; | 82 var result = argument; |
| 84 if (argument.contains('\t') || argument.contains(' ')) { | 83 if (argument.contains('\t') || argument.contains(' ')) { |
| 85 // Produce something that the C runtime on Windows will parse | 84 // Produce something that the C runtime on Windows will parse |
| 86 // back as this string. | 85 // back as this string. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 141 bool success = _startNative(_path, | 140 bool success = _startNative(_path, |
| 142 _arguments, | 141 _arguments, |
| 143 _workingDirectory, | 142 _workingDirectory, |
| 144 _environment, | 143 _environment, |
| 145 _in, | 144 _in, |
| 146 _out, | 145 _out, |
| 147 _err, | 146 _err, |
| 148 _exitHandler, | 147 _exitHandler, |
| 149 status); | 148 status); |
| 150 if (!success) { | 149 if (!success) { |
| 151 close(); | 150 _in.close(); |
| 151 _out.close(); |
| 152 _err.close(); |
| 153 _exitHandler.close(); |
| 152 completer.completeException( | 154 completer.completeException( |
| 153 new ProcessException(status._errorMessage, status._errorCode)); | 155 new ProcessException(status._errorMessage, status._errorCode)); |
| 154 return; | 156 return; |
| 155 } | 157 } |
| 156 _started = true; | 158 _started = true; |
| 157 | 159 |
| 158 _in._closed = false; | 160 _in._closed = false; |
| 159 _out._closed = false; | 161 _out._closed = false; |
| 160 _err._closed = false; | 162 _err._closed = false; |
| 161 _exitHandler._closed = false; | 163 _exitHandler._closed = false; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 178 var negative = _intFromBytes(ints, 4); | 180 var negative = _intFromBytes(ints, 4); |
| 179 assert(negative == 0 || negative == 1); | 181 assert(negative == 0 || negative == 1); |
| 180 return (negative == 0) ? code : -code; | 182 return (negative == 0) ? code : -code; |
| 181 } | 183 } |
| 182 | 184 |
| 183 void handleExit() { | 185 void handleExit() { |
| 184 _ended = true; | 186 _ended = true; |
| 185 if (_onExit !== null) { | 187 if (_onExit !== null) { |
| 186 _onExit(exitCode(exitDataBuffer)); | 188 _onExit(exitCode(exitDataBuffer)); |
| 187 } | 189 } |
| 190 _out.close(); |
| 188 } | 191 } |
| 189 | 192 |
| 190 exitDataRead += _exitHandler.inputStream.readInto( | 193 exitDataRead += _exitHandler.inputStream.readInto( |
| 191 exitDataBuffer, exitDataRead, EXIT_DATA_SIZE - exitDataRead); | 194 exitDataBuffer, exitDataRead, EXIT_DATA_SIZE - exitDataRead); |
| 192 if (exitDataRead == EXIT_DATA_SIZE) handleExit(); | 195 if (exitDataRead == EXIT_DATA_SIZE) handleExit(); |
| 193 }; | 196 }; |
| 194 | 197 |
| 195 completer.complete(this); | 198 completer.complete(this); |
| 196 }); | 199 }); |
| 197 return completer.future; | 200 return completer.future; |
| 198 } | 201 } |
| 199 | 202 |
| 200 bool _startNative(String path, | 203 bool _startNative(String path, |
| 201 List<String> arguments, | 204 List<String> arguments, |
| 202 String workingDirectory, | 205 String workingDirectory, |
| 203 List<String> environment, | 206 List<String> environment, |
| 204 Socket input, | 207 Socket input, |
| 205 Socket output, | 208 Socket output, |
| 206 Socket error, | 209 Socket error, |
| 207 Socket exitHandler, | 210 Socket exitHandler, |
| 208 _ProcessStartStatus status) native "Process_Start"; | 211 _ProcessStartStatus status) native "Process_Start"; |
| 209 | 212 |
| 210 InputStream get stdout { | 213 InputStream get stdout { |
| 211 if (_closed) { | |
| 212 throw new ProcessException("Process closed"); | |
| 213 } | |
| 214 return _in.inputStream; | 214 return _in.inputStream; |
| 215 } | 215 } |
| 216 | 216 |
| 217 InputStream get stderr { | 217 InputStream get stderr { |
| 218 if (_closed) { | |
| 219 throw new ProcessException("Process closed"); | |
| 220 } | |
| 221 return _err.inputStream; | 218 return _err.inputStream; |
| 222 } | 219 } |
| 223 | 220 |
| 224 OutputStream get stdin { | 221 OutputStream get stdin { |
| 225 if (_closed) { | |
| 226 throw new ProcessException("Process closed"); | |
| 227 } | |
| 228 return _out.outputStream; | 222 return _out.outputStream; |
| 229 } | 223 } |
| 230 | 224 |
| 231 bool kill([ProcessSignal signal = ProcessSignal.SIGTERM]) { | 225 bool kill([ProcessSignal signal = ProcessSignal.SIGTERM]) { |
| 232 if (signal is! ProcessSignal) { | 226 if (signal is! ProcessSignal) { |
| 233 throw new ArgumentError( | 227 throw new ArgumentError( |
| 234 "Argument 'signal' must be a ProcessSignal"); | 228 "Argument 'signal' must be a ProcessSignal"); |
| 235 } | 229 } |
| 236 assert(_started); | 230 assert(_started); |
| 237 if (_ended) return false; | 231 if (_ended) return false; |
| 238 return _kill(this, signal._signalNumber); | 232 return _kill(this, signal._signalNumber); |
| 239 } | 233 } |
| 240 | 234 |
| 241 bool _kill(Process p, int signal) native "Process_Kill"; | 235 bool _kill(Process p, int signal) native "Process_Kill"; |
| 242 | 236 |
| 243 void close() { | |
| 244 if (_closed) { | |
| 245 throw new ProcessException("Process closed"); | |
| 246 } | |
| 247 _in.close(); | |
| 248 _out.close(); | |
| 249 _err.close(); | |
| 250 _exitHandler.close(); | |
| 251 _closed = true; | |
| 252 } | |
| 253 | |
| 254 void set onExit(void callback(int exitCode)) { | 237 void set onExit(void callback(int exitCode)) { |
| 255 if (_closed) { | |
| 256 throw new ProcessException("Process closed"); | |
| 257 } | |
| 258 if (_ended) { | 238 if (_ended) { |
| 259 throw new ProcessException("Process killed"); | 239 throw new ProcessException("Process killed"); |
| 260 } | 240 } |
| 261 _onExit = callback; | 241 _onExit = callback; |
| 262 } | 242 } |
| 263 | 243 |
| 264 String _path; | 244 String _path; |
| 265 List<String> _arguments; | 245 List<String> _arguments; |
| 266 String _workingDirectory; | 246 String _workingDirectory; |
| 267 List<String> _environment; | 247 List<String> _environment; |
| 268 // Private methods of _Socket are used by _in, _out, and _err. | 248 // Private methods of _Socket are used by _in, _out, and _err. |
| 269 _Socket _in; | 249 _Socket _in; |
| 270 _Socket _out; | 250 _Socket _out; |
| 271 _Socket _err; | 251 _Socket _err; |
| 272 Socket _exitHandler; | 252 Socket _exitHandler; |
| 273 bool _closed; | |
| 274 bool _ended; | 253 bool _ended; |
| 275 bool _started; | 254 bool _started; |
| 276 Function _onExit; | 255 Function _onExit; |
| 277 } | 256 } |
| 278 | 257 |
| 279 | 258 |
| 280 // _NonInteractiveProcess is a wrapper around an interactive process | 259 // _NonInteractiveProcess is a wrapper around an interactive process |
| 281 // that buffers output so it can be delivered when the process exits. | 260 // that buffers output so it can be delivered when the process exits. |
| 282 // _NonInteractiveProcess is used to implement the Process.run | 261 // _NonInteractiveProcess is used to implement the Process.run |
| 283 // method. | 262 // method. |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 | 350 |
| 372 class _ProcessResult implements ProcessResult { | 351 class _ProcessResult implements ProcessResult { |
| 373 const _ProcessResult(int this.exitCode, | 352 const _ProcessResult(int this.exitCode, |
| 374 String this.stdout, | 353 String this.stdout, |
| 375 String this.stderr); | 354 String this.stderr); |
| 376 | 355 |
| 377 final int exitCode; | 356 final int exitCode; |
| 378 final String stdout; | 357 final String stdout; |
| 379 final String stderr; | 358 final String stderr; |
| 380 } | 359 } |
| OLD | NEW |