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

Unified Diff: runtime/bin/directory.cc

Issue 1893033002: Fixes memory leak of async directory lister (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Add unsupported calls 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/bin/directory.h ('k') | runtime/bin/directory_patch.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/bin/directory.cc
diff --git a/runtime/bin/directory.cc b/runtime/bin/directory.cc
index 982a4be0147d5ffad9e0696042a6f8b741c990e5..bb3173f5b63466d6d9bd5d90906edb41802f56b4 100644
--- a/runtime/bin/directory.cc
+++ b/runtime/bin/directory.cc
@@ -7,6 +7,7 @@
#include "bin/directory.h"
#include "bin/dartutils.h"
+#include "bin/log.h"
#include "include/dart_api.h"
#include "platform/assert.h"
@@ -139,6 +140,61 @@ void FUNCTION_NAME(Directory_List)(Dart_NativeArguments args) {
}
+static const int kAsyncDirectoryListerFieldIndex = 0;
+
+
+void FUNCTION_NAME(Directory_GetAsyncDirectoryListerPointer)(
+ Dart_NativeArguments args) {
+ AsyncDirectoryListing* listing;
+ Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
+ ASSERT(Dart_IsInstance(dart_this));
+ ThrowIfError(Dart_GetNativeInstanceField(
+ dart_this,
+ kAsyncDirectoryListerFieldIndex,
+ reinterpret_cast<intptr_t*>(&listing)));
+ if (listing != NULL) {
+ intptr_t listing_pointer = reinterpret_cast<intptr_t>(listing);
+ // Increment the listing's reference count. This native should only be
+ // be called when we are about to send the AsyncDirectoryListing* to the
+ // IO service.
+ listing->Retain();
+ Dart_SetReturnValue(args, Dart_NewInteger(listing_pointer));
+ }
+}
+
+
+static void ReleaseListing(void* isolate_callback_data,
+ Dart_WeakPersistentHandle handle,
+ void* peer) {
+ AsyncDirectoryListing* listing =
+ reinterpret_cast<AsyncDirectoryListing*>(peer);
+ listing->Release();
+}
+
+
+void FUNCTION_NAME(Directory_SetAsyncDirectoryListerPointer)(
+ Dart_NativeArguments args) {
+ Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
+ intptr_t listing_pointer =
+ DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 1));
+ AsyncDirectoryListing* listing =
+ reinterpret_cast<AsyncDirectoryListing*>(listing_pointer);
+ Dart_NewWeakPersistentHandle(
+ dart_this,
+ reinterpret_cast<void*>(listing),
+ sizeof(*listing),
+ ReleaseListing);
+ Dart_Handle result = Dart_SetNativeInstanceField(
+ dart_this,
+ kAsyncDirectoryListerFieldIndex,
+ listing_pointer);
+ if (Dart_IsError(result)) {
+ Log::PrintErr("SetAsyncDirectoryListerPointer failed\n");
+ Dart_PropagateError(result);
+ }
+}
+
+
CObject* Directory::CreateRequest(const CObjectArray& request) {
if ((request.Length() == 1) && request[0]->IsString()) {
CObjectString path(request[0]);
@@ -226,7 +282,7 @@ CObject* Directory::ListStartRequest(const CObjectArray& request) {
if (dir_listing->error()) {
// Report error now, so we capture the correct OSError.
CObject* err = CObject::NewOSError();
- delete dir_listing;
+ dir_listing->Release();
CObjectArray* error = new CObjectArray(CObject::NewArray(3));
error->SetAt(0, new CObjectInt32(
CObject::NewInt32(AsyncDirectoryListing::kListError)));
@@ -247,6 +303,7 @@ CObject* Directory::ListNextRequest(const CObjectArray& request) {
CObjectIntptr ptr(request[0]);
AsyncDirectoryListing* dir_listing =
reinterpret_cast<AsyncDirectoryListing*>(ptr.Value());
+ RefCntReleaseScope<AsyncDirectoryListing> rs(dir_listing);
if (dir_listing->IsEmpty()) {
return new CObjectArray(CObject::NewArray(0));
}
@@ -268,7 +325,15 @@ CObject* Directory::ListStopRequest(const CObjectArray& request) {
CObjectIntptr ptr(request[0]);
AsyncDirectoryListing* dir_listing =
reinterpret_cast<AsyncDirectoryListing*>(ptr.Value());
- delete dir_listing;
+ RefCntReleaseScope<AsyncDirectoryListing> rs(dir_listing);
+
+ // We have retained a reference to the listing here. Therefore the listing's
+ // destructor can't be running. Since no further requests are dispatched by
+ // the Dart code after an async stop call, this PopAll() can't be racing
+ // with any other call on the listing. We don't do an extra Release(), and
+ // we don't delete the weak persistent handle. The file is closed here, but
+ // the memory for the listing will be cleaned up when the finalizer runs.
+ dir_listing->PopAll();
return new CObjectBool(CObject::Bool(true));
}
return CreateIllegalArgumentError();
« no previous file with comments | « runtime/bin/directory.h ('k') | runtime/bin/directory_patch.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698