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

Side by Side Diff: sdk/lib/io/directory_impl.dart

Issue 1893033002: Fixes memory leak of async directory lister (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 months 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
« no previous file with comments | « runtime/bin/io_natives.cc ('k') | no next file » | 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 part of dart.io; 5 part of dart.io;
6 6
7 class _Directory extends FileSystemEntity implements Directory { 7 class _Directory extends FileSystemEntity implements Directory {
8 final String path; 8 final String path;
9 9
10 _Directory(this.path) { 10 _Directory(this.path) {
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 case _OSERROR_RESPONSE: 245 case _OSERROR_RESPONSE:
246 var err = new OSError(response[_OSERROR_RESPONSE_MESSAGE], 246 var err = new OSError(response[_OSERROR_RESPONSE_MESSAGE],
247 response[_OSERROR_RESPONSE_ERROR_CODE]); 247 response[_OSERROR_RESPONSE_ERROR_CODE]);
248 return new FileSystemException(message, path, err); 248 return new FileSystemException(message, path, err);
249 default: 249 default:
250 return new Exception("Unknown error"); 250 return new Exception("Unknown error");
251 } 251 }
252 } 252 }
253 } 253 }
254 254
255 abstract class _AsyncDirectoryListerOps {
256 external factory _AsyncDirectoryListerOps(int pointer);
Ivan Posva 2016/04/20 05:38:16 ditto. (Needs dart2js patch file.)
zra 2016/04/20 22:13:58 Done.
257
258 int getPointer();
259 }
260
255 class _AsyncDirectoryLister { 261 class _AsyncDirectoryLister {
256 static const int LIST_FILE = 0; 262 static const int LIST_FILE = 0;
257 static const int LIST_DIRECTORY = 1; 263 static const int LIST_DIRECTORY = 1;
258 static const int LIST_LINK = 2; 264 static const int LIST_LINK = 2;
259 static const int LIST_ERROR = 3; 265 static const int LIST_ERROR = 3;
260 static const int LIST_DONE = 4; 266 static const int LIST_DONE = 4;
261 267
262 static const int RESPONSE_TYPE = 0; 268 static const int RESPONSE_TYPE = 0;
263 static const int RESPONSE_PATH = 1; 269 static const int RESPONSE_PATH = 1;
264 static const int RESPONSE_COMPLETE = 1; 270 static const int RESPONSE_COMPLETE = 1;
265 static const int RESPONSE_ERROR = 2; 271 static const int RESPONSE_ERROR = 2;
266 272
267 final String path; 273 final String path;
268 final bool recursive; 274 final bool recursive;
269 final bool followLinks; 275 final bool followLinks;
270 276
271 StreamController controller; 277 StreamController controller;
272 int id;
273 bool canceled = false; 278 bool canceled = false;
274 bool nextRunning = false; 279 bool nextRunning = false;
275 bool closed = false; 280 bool closed = false;
281 _AsyncDirectoryListerOps _ops;
276 Completer closeCompleter = new Completer(); 282 Completer closeCompleter = new Completer();
277 283
278 _AsyncDirectoryLister(this.path, this.recursive, this.followLinks) { 284 _AsyncDirectoryLister(this.path, this.recursive, this.followLinks) {
279 controller = new StreamController(onListen: onListen, 285 controller = new StreamController(onListen: onListen,
280 onResume: onResume, 286 onResume: onResume,
281 onCancel: onCancel, 287 onCancel: onCancel,
282 sync: true); 288 sync: true);
283 } 289 }
284 290
291 int get _pointer => (_ops == null) ? null : _ops.getPointer();
292
285 Stream get stream => controller.stream; 293 Stream get stream => controller.stream;
286 294
287 void onListen() { 295 void onListen() {
288 _IOService._dispatch(_DIRECTORY_LIST_START, [path, recursive, followLinks]) 296 _IOService._dispatch(_DIRECTORY_LIST_START, [path, recursive, followLinks])
289 .then((response) { 297 .then((response) {
290 if (response is int) { 298 if (response is int) {
291 id = response; 299 _ops = new _AsyncDirectoryListerOps(response);
292 next(); 300 next();
293 } else if (response is Error) { 301 } else if (response is Error) {
294 controller.addError(response, response.stackTrace); 302 controller.addError(response, response.stackTrace);
295 close(); 303 close();
296 } else { 304 } else {
297 error(response); 305 error(response);
298 close(); 306 close();
299 } 307 }
300 }); 308 });
301 } 309 }
302 310
303 void onResume() { 311 void onResume() {
304 if (!nextRunning) next(); 312 if (!nextRunning) {
313 next();
314 }
305 } 315 }
306 316
307 Future onCancel() { 317 Future onCancel() {
308 canceled = true; 318 canceled = true;
309 // If we are active, but not requesting, close. 319 // If we are active, but not requesting, close.
310 if (!nextRunning) { 320 if (!nextRunning) {
311 close(); 321 close();
312 } 322 }
313 323
314 return closeCompleter.future; 324 return closeCompleter.future;
315 } 325 }
316 326
317 void next() { 327 void next() {
318 if (canceled) { 328 if (canceled) {
319 close(); 329 close();
320 return; 330 return;
321 } 331 }
322 if (id == null) return; 332 if ((_pointer == null) || controller.isPaused || nextRunning) {
323 if (controller.isPaused) return; 333 return;
324 if (nextRunning) return; 334 }
325 nextRunning = true; 335 nextRunning = true;
326 _IOService._dispatch(_DIRECTORY_LIST_NEXT, [id]).then((result) { 336 _IOService._dispatch(_DIRECTORY_LIST_NEXT, [_pointer]).then((result) {
327 nextRunning = false; 337 nextRunning = false;
328 if (result is List) { 338 if (result is List) {
329 next(); 339 next();
330 assert(result.length % 2 == 0); 340 assert(result.length % 2 == 0);
331 for (int i = 0; i < result.length; i++) { 341 for (int i = 0; i < result.length; i++) {
332 assert(i % 2 == 0); 342 assert(i % 2 == 0);
333 switch (result[i++]) { 343 switch (result[i++]) {
334 case LIST_FILE: 344 case LIST_FILE:
335 controller.add(new File(result[i])); 345 controller.add(new File(result[i]));
336 break; 346 break;
(...skipping 10 matching lines...) Expand all
347 canceled = true; 357 canceled = true;
348 return; 358 return;
349 } 359 }
350 } 360 }
351 } else { 361 } else {
352 controller.addError(new FileSystemException("Internal error")); 362 controller.addError(new FileSystemException("Internal error"));
353 } 363 }
354 }); 364 });
355 } 365 }
356 366
367 void _cleanup() {
368 controller.close();
369 closeCompleter.complete();
370 _ops = null;
371 }
372
357 void close() { 373 void close() {
358 if (closed) return; 374 if (closed) {
359 if (nextRunning) return; 375 return;
360 void cleanup() { 376 }
361 controller.close(); 377 if (nextRunning) {
362 closeCompleter.complete(); 378 return;
363 } 379 }
364 closed = true; 380 closed = true;
365 if (id != null) { 381 if (_pointer != null) {
366 _IOService._dispatch(_DIRECTORY_LIST_STOP, [id]).whenComplete(cleanup); 382 _IOService._dispatch(_DIRECTORY_LIST_STOP, [_pointer])
383 .whenComplete(_cleanup);
367 } else { 384 } else {
368 cleanup(); 385 _cleanup();
369 } 386 }
370 } 387 }
371 388
372 void error(message) { 389 void error(message) {
373 var errorType = 390 var errorType =
374 message[RESPONSE_ERROR][_ERROR_RESPONSE_ERROR_TYPE]; 391 message[RESPONSE_ERROR][_ERROR_RESPONSE_ERROR_TYPE];
375 if (errorType == _ILLEGAL_ARGUMENT_RESPONSE) { 392 if (errorType == _ILLEGAL_ARGUMENT_RESPONSE) {
376 controller.addError(new ArgumentError()); 393 controller.addError(new ArgumentError());
377 } else if (errorType == _OSERROR_RESPONSE) { 394 } else if (errorType == _OSERROR_RESPONSE) {
378 var responseError = message[RESPONSE_ERROR]; 395 var responseError = message[RESPONSE_ERROR];
379 var err = new OSError( 396 var err = new OSError(
380 responseError[_OSERROR_RESPONSE_MESSAGE], 397 responseError[_OSERROR_RESPONSE_MESSAGE],
381 responseError[_OSERROR_RESPONSE_ERROR_CODE]); 398 responseError[_OSERROR_RESPONSE_ERROR_CODE]);
382 var errorPath = message[RESPONSE_PATH]; 399 var errorPath = message[RESPONSE_PATH];
383 if (errorPath == null) errorPath = path; 400 if (errorPath == null) errorPath = path;
384 controller.addError( 401 controller.addError(
385 new FileSystemException("Directory listing failed", 402 new FileSystemException("Directory listing failed",
386 errorPath, 403 errorPath,
387 err)); 404 err));
388 } else { 405 } else {
389 controller.addError( 406 controller.addError(
390 new FileSystemException("Internal error")); 407 new FileSystemException("Internal error"));
391 } 408 }
392 } 409 }
393 } 410 }
OLDNEW
« no previous file with comments | « runtime/bin/io_natives.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698