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

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: 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 unified diff | Download patch
« no previous file with comments | « runtime/bin/directory.h ('k') | runtime/bin/directory_patch.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 #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_NewWeakPersistentHandle(
183 dart_this,
184 reinterpret_cast<void*>(listing),
185 sizeof(*listing),
186 ReleaseListing);
187 Dart_Handle result = Dart_SetNativeInstanceField(
188 dart_this,
189 kAsyncDirectoryListerFieldIndex,
190 listing_pointer);
191 if (Dart_IsError(result)) {
192 Log::PrintErr("SetAsyncDirectoryListerPointer failed\n");
193 Dart_PropagateError(result);
194 }
195 }
196
197
142 CObject* Directory::CreateRequest(const CObjectArray& request) { 198 CObject* Directory::CreateRequest(const CObjectArray& request) {
143 if ((request.Length() == 1) && request[0]->IsString()) { 199 if ((request.Length() == 1) && request[0]->IsString()) {
144 CObjectString path(request[0]); 200 CObjectString path(request[0]);
145 if (Directory::Create(path.CString())) { 201 if (Directory::Create(path.CString())) {
146 return CObject::True(); 202 return CObject::True();
147 } else { 203 } else {
148 return CObject::NewOSError(); 204 return CObject::NewOSError();
149 } 205 }
150 } 206 }
151 return CObject::IllegalArgumentError(); 207 return CObject::IllegalArgumentError();
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 CObjectString path(request[0]); 275 CObjectString path(request[0]);
220 CObjectBool recursive(request[1]); 276 CObjectBool recursive(request[1]);
221 CObjectBool follow_links(request[2]); 277 CObjectBool follow_links(request[2]);
222 AsyncDirectoryListing* dir_listing = 278 AsyncDirectoryListing* dir_listing =
223 new AsyncDirectoryListing(path.CString(), 279 new AsyncDirectoryListing(path.CString(),
224 recursive.Value(), 280 recursive.Value(),
225 follow_links.Value()); 281 follow_links.Value());
226 if (dir_listing->error()) { 282 if (dir_listing->error()) {
227 // Report error now, so we capture the correct OSError. 283 // Report error now, so we capture the correct OSError.
228 CObject* err = CObject::NewOSError(); 284 CObject* err = CObject::NewOSError();
229 delete dir_listing; 285 dir_listing->Release();
230 CObjectArray* error = new CObjectArray(CObject::NewArray(3)); 286 CObjectArray* error = new CObjectArray(CObject::NewArray(3));
231 error->SetAt(0, new CObjectInt32( 287 error->SetAt(0, new CObjectInt32(
232 CObject::NewInt32(AsyncDirectoryListing::kListError))); 288 CObject::NewInt32(AsyncDirectoryListing::kListError)));
233 error->SetAt(1, request[0]); 289 error->SetAt(1, request[0]);
234 error->SetAt(2, err); 290 error->SetAt(2, err);
235 return error; 291 return error;
236 } 292 }
237 // TODO(ajohnsen): Consider returning the first few results. 293 // TODO(ajohnsen): Consider returning the first few results.
238 return new CObjectIntptr(CObject::NewIntptr( 294 return new CObjectIntptr(CObject::NewIntptr(
239 reinterpret_cast<intptr_t>(dir_listing))); 295 reinterpret_cast<intptr_t>(dir_listing)));
240 } 296 }
241 return CreateIllegalArgumentError(); 297 return CreateIllegalArgumentError();
242 } 298 }
243 299
244 300
245 CObject* Directory::ListNextRequest(const CObjectArray& request) { 301 CObject* Directory::ListNextRequest(const CObjectArray& request) {
246 if ((request.Length() == 1) && request[0]->IsIntptr()) { 302 if ((request.Length() == 1) && request[0]->IsIntptr()) {
247 CObjectIntptr ptr(request[0]); 303 CObjectIntptr ptr(request[0]);
248 AsyncDirectoryListing* dir_listing = 304 AsyncDirectoryListing* dir_listing =
249 reinterpret_cast<AsyncDirectoryListing*>(ptr.Value()); 305 reinterpret_cast<AsyncDirectoryListing*>(ptr.Value());
306 RefCntReleaseScope<AsyncDirectoryListing> rs(dir_listing);
250 if (dir_listing->IsEmpty()) { 307 if (dir_listing->IsEmpty()) {
251 return new CObjectArray(CObject::NewArray(0)); 308 return new CObjectArray(CObject::NewArray(0));
252 } 309 }
253 const int kArraySize = 128; 310 const int kArraySize = 128;
254 CObjectArray* response = new CObjectArray(CObject::NewArray(kArraySize)); 311 CObjectArray* response = new CObjectArray(CObject::NewArray(kArraySize));
255 dir_listing->SetArray(response, kArraySize); 312 dir_listing->SetArray(response, kArraySize);
256 Directory::List(dir_listing); 313 Directory::List(dir_listing);
257 // In case the listing ended before it hit the buffer length, we need to 314 // In case the listing ended before it hit the buffer length, we need to
258 // override the array length. 315 // override the array length.
259 response->AsApiCObject()->value.as_array.length = dir_listing->index(); 316 response->AsApiCObject()->value.as_array.length = dir_listing->index();
260 return response; 317 return response;
261 } 318 }
262 return CreateIllegalArgumentError(); 319 return CreateIllegalArgumentError();
263 } 320 }
264 321
265 322
266 CObject* Directory::ListStopRequest(const CObjectArray& request) { 323 CObject* Directory::ListStopRequest(const CObjectArray& request) {
267 if ((request.Length() == 1) && request[0]->IsIntptr()) { 324 if ((request.Length() == 1) && request[0]->IsIntptr()) {
268 CObjectIntptr ptr(request[0]); 325 CObjectIntptr ptr(request[0]);
269 AsyncDirectoryListing* dir_listing = 326 AsyncDirectoryListing* dir_listing =
270 reinterpret_cast<AsyncDirectoryListing*>(ptr.Value()); 327 reinterpret_cast<AsyncDirectoryListing*>(ptr.Value());
271 delete dir_listing; 328 RefCntReleaseScope<AsyncDirectoryListing> rs(dir_listing);
329
330 // We have retained a reference to the listing here. Therefore the listing's
331 // destructor can't be running. Since no further requests are dispatched by
332 // the Dart code after an async stop call, this PopAll() can't be racing
333 // with any other call on the listing. We don't do an extra Release(), and
334 // we don't delete the weak persistent handle. The file is closed here, but
335 // the memory for the listing will be cleaned up when the finalizer runs.
336 dir_listing->PopAll();
272 return new CObjectBool(CObject::Bool(true)); 337 return new CObjectBool(CObject::Bool(true));
273 } 338 }
274 return CreateIllegalArgumentError(); 339 return CreateIllegalArgumentError();
275 } 340 }
276 341
277 342
278 CObject* Directory::RenameRequest(const CObjectArray& request) { 343 CObject* Directory::RenameRequest(const CObjectArray& request) {
279 if ((request.Length() == 2) && 344 if ((request.Length() == 2) &&
280 request[0]->IsString() && 345 request[0]->IsString() &&
281 request[1]->IsString()) { 346 request[1]->IsString()) {
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
419 listing->HandleDone(); 484 listing->HandleDone();
420 } else { 485 } else {
421 while (ListNext(listing)) {} 486 while (ListNext(listing)) {}
422 } 487 }
423 } 488 }
424 489
425 } // namespace bin 490 } // namespace bin
426 } // namespace dart 491 } // namespace dart
427 492
428 #endif // !defined(DART_IO_DISABLED) 493 #endif // !defined(DART_IO_DISABLED)
OLDNEW
« 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