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

Side by Side 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: 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
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 #if !defined(DART_IO_DISABLED) 5 #if !defined(DART_IO_DISABLED)
6 6
7 #include "bin/directory.h" 7 #include "bin/directory.h"
8 8
9 #include "bin/dartutils.h" 9 #include "bin/dartutils.h"
10 #include "bin/log.h"
10 #include "include/dart_api.h" 11 #include "include/dart_api.h"
11 #include "platform/assert.h" 12 #include "platform/assert.h"
12 13
13 namespace dart { 14 namespace dart {
14 namespace bin { 15 namespace bin {
15 16
16 void FUNCTION_NAME(Directory_Current)(Dart_NativeArguments args) { 17 void FUNCTION_NAME(Directory_Current)(Dart_NativeArguments args) {
17 const char* current = Directory::Current(); 18 const char* current = Directory::Current();
18 if (current != NULL) { 19 if (current != NULL) {
19 Dart_SetReturnValue(args, DartUtils::NewString(current)); 20 Dart_SetReturnValue(args, DartUtils::NewString(current));
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 } 133 }
133 SyncDirectoryListing sync_listing(results, 134 SyncDirectoryListing sync_listing(results,
134 DartUtils::GetStringValue(path), 135 DartUtils::GetStringValue(path),
135 DartUtils::GetBooleanValue(recursive), 136 DartUtils::GetBooleanValue(recursive),
136 DartUtils::GetBooleanValue(follow_links)); 137 DartUtils::GetBooleanValue(follow_links));
137 Directory::List(&sync_listing); 138 Directory::List(&sync_listing);
138 Dart_SetReturnValue(args, results); 139 Dart_SetReturnValue(args, results);
139 } 140 }
140 141
141 142
143 static const int kAsyncDirectoryListerFieldIndex = 0;
144
145
146 void FUNCTION_NAME(Directory_GetAsyncDirectoryListerPointer)(
147 Dart_NativeArguments args) {
148 AsyncDirectoryListing* listing;
149 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
150 ASSERT(Dart_IsInstance(dart_this));
151 ThrowIfError(Dart_GetNativeInstanceField(
152 dart_this,
153 kAsyncDirectoryListerFieldIndex,
154 reinterpret_cast<intptr_t*>(&listing)));
155 if (listing != NULL) {
156 intptr_t listing_pointer = reinterpret_cast<intptr_t>(listing);
157 // Increment the listing's reference count. This native should only be
158 // be called when we are about to send the AsyncDirectoryListing* to the
159 // IO service.
160 listing->Retain();
161 Dart_SetReturnValue(args, Dart_NewInteger(listing_pointer));
162 }
163 }
164
165
166 static void ReleaseListing(void* isolate_callback_data,
167 Dart_WeakPersistentHandle handle,
168 void* peer) {
169 AsyncDirectoryListing* listing =
170 reinterpret_cast<AsyncDirectoryListing*>(peer);
171 listing->Release();
172 }
173
174
175 void FUNCTION_NAME(Directory_SetAsyncDirectoryListerPointer)(
176 Dart_NativeArguments args) {
177 Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
178 intptr_t listing_pointer =
179 DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 1));
180 AsyncDirectoryListing* listing =
181 reinterpret_cast<AsyncDirectoryListing*>(listing_pointer);
182 Dart_WeakPersistentHandle handle = Dart_NewWeakPersistentHandle(
183 dart_this,
184 reinterpret_cast<void*>(listing),
185 sizeof(*listing),
186 ReleaseListing);
187 listing->SetWeakHandle(handle);
188 Dart_Handle result = Dart_SetNativeInstanceField(
189 dart_this,
190 kAsyncDirectoryListerFieldIndex,
191 listing_pointer);
192 if (Dart_IsError(result)) {
193 Log::PrintErr("SetAsyncDirectoryListerPointer failed\n");
194 Dart_PropagateError(result);
195 }
196 }
197
198
142 CObject* Directory::CreateRequest(const CObjectArray& request) { 199 CObject* Directory::CreateRequest(const CObjectArray& request) {
143 if ((request.Length() == 1) && request[0]->IsString()) { 200 if ((request.Length() == 1) && request[0]->IsString()) {
144 CObjectString path(request[0]); 201 CObjectString path(request[0]);
145 if (Directory::Create(path.CString())) { 202 if (Directory::Create(path.CString())) {
146 return CObject::True(); 203 return CObject::True();
147 } else { 204 } else {
148 return CObject::NewOSError(); 205 return CObject::NewOSError();
149 } 206 }
150 } 207 }
151 return CObject::IllegalArgumentError(); 208 return CObject::IllegalArgumentError();
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 CObjectString path(request[0]); 276 CObjectString path(request[0]);
220 CObjectBool recursive(request[1]); 277 CObjectBool recursive(request[1]);
221 CObjectBool follow_links(request[2]); 278 CObjectBool follow_links(request[2]);
222 AsyncDirectoryListing* dir_listing = 279 AsyncDirectoryListing* dir_listing =
223 new AsyncDirectoryListing(path.CString(), 280 new AsyncDirectoryListing(path.CString(),
224 recursive.Value(), 281 recursive.Value(),
225 follow_links.Value()); 282 follow_links.Value());
226 if (dir_listing->error()) { 283 if (dir_listing->error()) {
227 // Report error now, so we capture the correct OSError. 284 // Report error now, so we capture the correct OSError.
228 CObject* err = CObject::NewOSError(); 285 CObject* err = CObject::NewOSError();
229 delete dir_listing; 286 dir_listing->Release();
230 CObjectArray* error = new CObjectArray(CObject::NewArray(3)); 287 CObjectArray* error = new CObjectArray(CObject::NewArray(3));
231 error->SetAt(0, new CObjectInt32( 288 error->SetAt(0, new CObjectInt32(
232 CObject::NewInt32(AsyncDirectoryListing::kListError))); 289 CObject::NewInt32(AsyncDirectoryListing::kListError)));
233 error->SetAt(1, request[0]); 290 error->SetAt(1, request[0]);
234 error->SetAt(2, err); 291 error->SetAt(2, err);
235 return error; 292 return error;
236 } 293 }
237 // TODO(ajohnsen): Consider returning the first few results. 294 // TODO(ajohnsen): Consider returning the first few results.
238 return new CObjectIntptr(CObject::NewIntptr( 295 return new CObjectIntptr(CObject::NewIntptr(
239 reinterpret_cast<intptr_t>(dir_listing))); 296 reinterpret_cast<intptr_t>(dir_listing)));
240 } 297 }
241 return CreateIllegalArgumentError(); 298 return CreateIllegalArgumentError();
242 } 299 }
243 300
244 301
245 CObject* Directory::ListNextRequest(const CObjectArray& request) { 302 CObject* Directory::ListNextRequest(const CObjectArray& request) {
246 if ((request.Length() == 1) && request[0]->IsIntptr()) { 303 if ((request.Length() == 1) && request[0]->IsIntptr()) {
247 CObjectIntptr ptr(request[0]); 304 CObjectIntptr ptr(request[0]);
248 AsyncDirectoryListing* dir_listing = 305 AsyncDirectoryListing* dir_listing =
249 reinterpret_cast<AsyncDirectoryListing*>(ptr.Value()); 306 reinterpret_cast<AsyncDirectoryListing*>(ptr.Value());
307 RefCntReleaseScope<AsyncDirectoryListing> rs(dir_listing);
250 if (dir_listing->IsEmpty()) { 308 if (dir_listing->IsEmpty()) {
251 return new CObjectArray(CObject::NewArray(0)); 309 return new CObjectArray(CObject::NewArray(0));
252 } 310 }
253 const int kArraySize = 128; 311 const int kArraySize = 128;
254 CObjectArray* response = new CObjectArray(CObject::NewArray(kArraySize)); 312 CObjectArray* response = new CObjectArray(CObject::NewArray(kArraySize));
255 dir_listing->SetArray(response, kArraySize); 313 dir_listing->SetArray(response, kArraySize);
256 Directory::List(dir_listing); 314 Directory::List(dir_listing);
257 // In case the listing ended before it hit the buffer length, we need to 315 // In case the listing ended before it hit the buffer length, we need to
258 // override the array length. 316 // override the array length.
259 response->AsApiCObject()->value.as_array.length = dir_listing->index(); 317 response->AsApiCObject()->value.as_array.length = dir_listing->index();
260 return response; 318 return response;
261 } 319 }
262 return CreateIllegalArgumentError(); 320 return CreateIllegalArgumentError();
263 } 321 }
264 322
265 323
266 CObject* Directory::ListStopRequest(const CObjectArray& request) { 324 CObject* Directory::ListStopRequest(const CObjectArray& request) {
267 if ((request.Length() == 1) && request[0]->IsIntptr()) { 325 if ((request.Length() == 1) && request[0]->IsIntptr()) {
268 CObjectIntptr ptr(request[0]); 326 CObjectIntptr ptr(request[0]);
269 AsyncDirectoryListing* dir_listing = 327 AsyncDirectoryListing* dir_listing =
270 reinterpret_cast<AsyncDirectoryListing*>(ptr.Value()); 328 reinterpret_cast<AsyncDirectoryListing*>(ptr.Value());
271 delete dir_listing; 329 RefCntReleaseScope<AsyncDirectoryListing> rs(dir_listing);
330
331 // We have retained a reference to the listing here. Therefore the listing's
332 // destructor can't be running. Since no further requests are dispatched by
333 // the Dart code after an async stop call, this PopAll() can't be racing
334 // with any other call on the listing. We don't do an extra Release(), and
335 // we don't delete the weak persistent handle. The file is closed here, but
336 // the memory for the listing will be cleaned up when the finalizer runs.
337 dir_listing->PopAll();
272 return new CObjectBool(CObject::Bool(true)); 338 return new CObjectBool(CObject::Bool(true));
273 } 339 }
274 return CreateIllegalArgumentError(); 340 return CreateIllegalArgumentError();
275 } 341 }
276 342
277 343
278 CObject* Directory::RenameRequest(const CObjectArray& request) { 344 CObject* Directory::RenameRequest(const CObjectArray& request) {
279 if ((request.Length() == 2) && 345 if ((request.Length() == 2) &&
280 request[0]->IsString() && 346 request[0]->IsString() &&
281 request[1]->IsString()) { 347 request[1]->IsString()) {
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
419 listing->HandleDone(); 485 listing->HandleDone();
420 } else { 486 } else {
421 while (ListNext(listing)) {} 487 while (ListNext(listing)) {}
422 } 488 }
423 } 489 }
424 490
425 } // namespace bin 491 } // namespace bin
426 } // namespace dart 492 } // namespace dart
427 493
428 #endif // !defined(DART_IO_DISABLED) 494 #endif // !defined(DART_IO_DISABLED)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698