| 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();
|
|
|