Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(600)

Side by Side Diff: runtime/bin/process_impl.dart

Issue 11343009: Get rid of 'close' on process. It is very easy to use incorrectly and cut off data from your stream… (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comment. Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/bin/process.dart ('k') | tests/standalone/io/dart_std_io_pipe_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « runtime/bin/process.dart ('k') | tests/standalone/io/dart_std_io_pipe_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698