Chromium Code Reviews| 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 _close(); |
| 152 completer.completeException( | 151 completer.completeException( |
| 153 new ProcessException(status._errorMessage, status._errorCode)); | 152 new ProcessException(status._errorMessage, status._errorCode)); |
| 154 return; | 153 return; |
| 155 } | 154 } |
| 156 _started = true; | 155 _started = true; |
| 157 | 156 |
| 158 _in._closed = false; | 157 _in._closed = false; |
| 159 _out._closed = false; | 158 _out._closed = false; |
| 160 _err._closed = false; | 159 _err._closed = false; |
| 161 _exitHandler._closed = false; | 160 _exitHandler._closed = false; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 178 var negative = _intFromBytes(ints, 4); | 177 var negative = _intFromBytes(ints, 4); |
| 179 assert(negative == 0 || negative == 1); | 178 assert(negative == 0 || negative == 1); |
| 180 return (negative == 0) ? code : -code; | 179 return (negative == 0) ? code : -code; |
| 181 } | 180 } |
| 182 | 181 |
| 183 void handleExit() { | 182 void handleExit() { |
| 184 _ended = true; | 183 _ended = true; |
| 185 if (_onExit !== null) { | 184 if (_onExit !== null) { |
| 186 _onExit(exitCode(exitDataBuffer)); | 185 _onExit(exitCode(exitDataBuffer)); |
| 187 } | 186 } |
| 187 _out.close(); | |
| 188 } | 188 } |
| 189 | 189 |
| 190 exitDataRead += _exitHandler.inputStream.readInto( | 190 exitDataRead += _exitHandler.inputStream.readInto( |
| 191 exitDataBuffer, exitDataRead, EXIT_DATA_SIZE - exitDataRead); | 191 exitDataBuffer, exitDataRead, EXIT_DATA_SIZE - exitDataRead); |
| 192 if (exitDataRead == EXIT_DATA_SIZE) handleExit(); | 192 if (exitDataRead == EXIT_DATA_SIZE) handleExit(); |
| 193 }; | 193 }; |
| 194 | 194 |
| 195 completer.complete(this); | 195 completer.complete(this); |
| 196 }); | 196 }); |
| 197 return completer.future; | 197 return completer.future; |
| 198 } | 198 } |
| 199 | 199 |
| 200 bool _startNative(String path, | 200 bool _startNative(String path, |
| 201 List<String> arguments, | 201 List<String> arguments, |
| 202 String workingDirectory, | 202 String workingDirectory, |
| 203 List<String> environment, | 203 List<String> environment, |
| 204 Socket input, | 204 Socket input, |
| 205 Socket output, | 205 Socket output, |
| 206 Socket error, | 206 Socket error, |
| 207 Socket exitHandler, | 207 Socket exitHandler, |
| 208 _ProcessStartStatus status) native "Process_Start"; | 208 _ProcessStartStatus status) native "Process_Start"; |
| 209 | 209 |
| 210 InputStream get stdout { | 210 InputStream get stdout { |
| 211 if (_closed) { | |
| 212 throw new ProcessException("Process closed"); | |
| 213 } | |
| 214 return _in.inputStream; | 211 return _in.inputStream; |
| 215 } | 212 } |
| 216 | 213 |
| 217 InputStream get stderr { | 214 InputStream get stderr { |
| 218 if (_closed) { | |
| 219 throw new ProcessException("Process closed"); | |
| 220 } | |
| 221 return _err.inputStream; | 215 return _err.inputStream; |
| 222 } | 216 } |
| 223 | 217 |
| 224 OutputStream get stdin { | 218 OutputStream get stdin { |
| 225 if (_closed) { | |
| 226 throw new ProcessException("Process closed"); | |
| 227 } | |
| 228 return _out.outputStream; | 219 return _out.outputStream; |
| 229 } | 220 } |
| 230 | 221 |
| 231 bool kill([ProcessSignal signal = ProcessSignal.SIGTERM]) { | 222 bool kill([ProcessSignal signal = ProcessSignal.SIGTERM]) { |
| 232 if (signal is! ProcessSignal) { | 223 if (signal is! ProcessSignal) { |
| 233 throw new ArgumentError( | 224 throw new ArgumentError( |
| 234 "Argument 'signal' must be a ProcessSignal"); | 225 "Argument 'signal' must be a ProcessSignal"); |
| 235 } | 226 } |
| 236 assert(_started); | 227 assert(_started); |
| 237 if (_ended) return false; | 228 if (_ended) return false; |
| 238 return _kill(this, signal._signalNumber); | 229 return _kill(this, signal._signalNumber); |
| 239 } | 230 } |
| 240 | 231 |
| 241 bool _kill(Process p, int signal) native "Process_Kill"; | 232 bool _kill(Process p, int signal) native "Process_Kill"; |
| 242 | 233 |
| 243 void close() { | 234 void _close() { |
|
Søren Gjesse
2012/10/29 11:43:24
_close is only used in one place - when starting a
Mads Ager (google)
2012/10/29 11:50:05
Thanks. Done.
| |
| 244 if (_closed) { | |
| 245 throw new ProcessException("Process closed"); | |
| 246 } | |
| 247 _in.close(); | 235 _in.close(); |
| 248 _out.close(); | 236 _out.close(); |
| 249 _err.close(); | 237 _err.close(); |
| 250 _exitHandler.close(); | 238 _exitHandler.close(); |
| 251 _closed = true; | |
| 252 } | 239 } |
| 253 | 240 |
| 254 void set onExit(void callback(int exitCode)) { | 241 void set onExit(void callback(int exitCode)) { |
| 255 if (_closed) { | |
| 256 throw new ProcessException("Process closed"); | |
| 257 } | |
| 258 if (_ended) { | 242 if (_ended) { |
| 259 throw new ProcessException("Process killed"); | 243 throw new ProcessException("Process killed"); |
| 260 } | 244 } |
| 261 _onExit = callback; | 245 _onExit = callback; |
| 262 } | 246 } |
| 263 | 247 |
| 264 String _path; | 248 String _path; |
| 265 List<String> _arguments; | 249 List<String> _arguments; |
| 266 String _workingDirectory; | 250 String _workingDirectory; |
| 267 List<String> _environment; | 251 List<String> _environment; |
| 268 // Private methods of _Socket are used by _in, _out, and _err. | 252 // Private methods of _Socket are used by _in, _out, and _err. |
| 269 _Socket _in; | 253 _Socket _in; |
| 270 _Socket _out; | 254 _Socket _out; |
| 271 _Socket _err; | 255 _Socket _err; |
| 272 Socket _exitHandler; | 256 Socket _exitHandler; |
| 273 bool _closed; | |
| 274 bool _ended; | 257 bool _ended; |
| 275 bool _started; | 258 bool _started; |
| 276 Function _onExit; | 259 Function _onExit; |
| 277 } | 260 } |
| 278 | 261 |
| 279 | 262 |
| 280 // _NonInteractiveProcess is a wrapper around an interactive process | 263 // _NonInteractiveProcess is a wrapper around an interactive process |
| 281 // that buffers output so it can be delivered when the process exits. | 264 // that buffers output so it can be delivered when the process exits. |
| 282 // _NonInteractiveProcess is used to implement the Process.run | 265 // _NonInteractiveProcess is used to implement the Process.run |
| 283 // method. | 266 // method. |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 371 | 354 |
| 372 class _ProcessResult implements ProcessResult { | 355 class _ProcessResult implements ProcessResult { |
| 373 const _ProcessResult(int this.exitCode, | 356 const _ProcessResult(int this.exitCode, |
| 374 String this.stdout, | 357 String this.stdout, |
| 375 String this.stderr); | 358 String this.stderr); |
| 376 | 359 |
| 377 final int exitCode; | 360 final int exitCode; |
| 378 final String stdout; | 361 final String stdout; |
| 379 final String stderr; | 362 final String stderr; |
| 380 } | 363 } |
| OLD | NEW |