Changeset 101813 in webkit
- Timestamp:
- Dec 2, 2011 9:42:54 AM (12 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r101812 r101813 1 2011-12-01 Darin Adler <darin@apple.com> 2 3 [Mac] Reference count threading violation in FormDataStreamMac.mm 4 https://bugs.webkit.org/show_bug.cgi?id=73627 5 6 Reviewed by Sam Weinig. 7 8 Shows up as a crash during existing layout test runs so no new tests are required. 9 10 * platform/network/mac/FormDataStreamMac.mm: 11 (WebCore::streamFieldsMap): Replaced getStreamFormDataMap with this. 12 Use an NSMapTable instead of a HashMap because we need to remove items from this 13 on a non-main thread. 14 (WebCore::associateStreamWithResourceHandle): Use NSMapGet instead of 15 HashMap::contains here. 16 (WebCore::formCreate): FormStreamFields now stores a RefPtr to the form data. 17 Added the code to fill that in. Did it in a more modern way to avoid the leakRef 18 and adoptRef that were used before. Replaced the code that set up the stream 19 form data map entry with code that sets an entry in the streamFieldsMap. 20 (WebCore::formFinishFinalizationOnMainThread): Added. Contains the work of 21 finalization that must be done on the main thread, specifically, destroying the 22 fields structure that contains objects with RefPtr in them. We can't touch these 23 reference counts on non-main threads. 24 (WebCore::formFinalize): Changed this to use NSMapRemove on the streamFieldsMap. 25 Added a callOnMainThread to finish the finalization. 26 (WebCore::setHTTPBody): Removed the leakRef, no longer needed, that used to be 27 balanced by an adoptRef in formCreate. 28 (WebCore::httpBodyFromStream): Changed to use NSMapGet. 29 1 30 2011-12-02 Antti Koivisto <antti@apple.com> 2 31 -
trunk/Source/WebCore/platform/network/mac/FormDataStreamMac.mm
r89283 r101813 1 1 /* 2 * Copyright (C) 2005, 2006, 2008 Apple Inc.All rights reserved.2 * Copyright (C) 2005, 2006, 2008, 2011 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 57 57 namespace WebCore { 58 58 59 typedef HashMap<CFReadStreamRef, RefPtr<FormData> > StreamFormDataMap; 60 static StreamFormDataMap& getStreamFormDataMap()61 { 62 DEFINE_STATIC_LOCAL(StreamFormDataMap, streamFormDataMap, ());63 return streamF ormDataMap;59 // We need to use NSMapTable instead of HashMap since this needs to be accessed from more than one thread. 60 static NSMapTable *streamFieldsMap() 61 { 62 static NSMapTable *streamFieldsMap = NSCreateMapTable(NSNonRetainedObjectMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, 1); 63 return streamFieldsMap; 64 64 } 65 65 … … 80 80 return; 81 81 82 if (! getStreamFormDataMap().contains((CFReadStreamRef)stream))82 if (!NSMapGet(streamFieldsMap(), stream)) 83 83 return; 84 84 … … 126 126 127 127 struct FormContext { 128 FormData*formData;128 RefPtr<FormData> formData; 129 129 unsigned long long streamLength; 130 130 }; 131 131 132 132 struct FormStreamFields { 133 RefPtr<FormData> formData; 133 134 SchedulePairHashSet scheduledRunLoopPairs; 134 135 Vector<FormDataElement> remainingElements; // in reverse order … … 231 232 232 233 FormStreamFields* newInfo = new FormStreamFields; 234 newInfo->formData = formContext->formData.release(); 233 235 newInfo->currentStream = NULL; 234 236 #if ENABLE(BLOB) … … 240 242 newInfo->bytesSent = 0; 241 243 242 FormData* formData = formContext->formData;243 244 244 // Append in reverse order since we remove elements from the end. 245 size_t size = formData->elements().size();245 size_t size = newInfo->formData->elements().size(); 246 246 newInfo->remainingElements.reserveInitialCapacity(size); 247 247 for (size_t i = 0; i < size; ++i) 248 newInfo->remainingElements.append(formData->elements()[size - i - 1]); 249 250 getStreamFormDataMap().set(stream, adoptRef(formData)); 248 newInfo->remainingElements.append(newInfo->formData->elements()[size - i - 1]); 249 250 ASSERT(!NSMapGet(streamFieldsMap(), stream)); 251 NSMapInsertKnownAbsent(streamFieldsMap(), stream, newInfo); 251 252 252 253 return newInfo; 253 254 } 254 255 256 static void formFinishFinalizationOnMainThread(void* context) 257 { 258 OwnPtr<FormStreamFields> form = adoptPtr(static_cast<FormStreamFields*>(context)); 259 260 closeCurrentStream(form.get()); 261 } 262 255 263 static void formFinalize(CFReadStreamRef stream, void* context) 256 264 { 257 OwnPtr<FormStreamFields> form = adoptPtr(static_cast<FormStreamFields*>(context)); 258 259 getStreamFormDataMap().remove(stream); 260 261 closeCurrentStream(form.get()); 265 FormStreamFields* form = static_cast<FormStreamFields*>(context); 266 267 ASSERT(form->formStream == stream); 268 ASSERT(NSMapGet(streamFieldsMap(), stream) == context); 269 270 // Do this right away because the CFReadStreamRef is being deallocated. 271 // We can't wait to remove this from the map until we finish finalizing 272 // on the main thread because in theory the freed memory could be reused 273 // for a new CFReadStream before that runs. 274 NSMapRemove(streamFieldsMap(), stream); 275 276 callOnMainThread(formFinishFinalizationOnMainThread, form); 262 277 } 263 278 … … 472 487 473 488 // Pass the length along with the formData so it does not have to be recomputed. 474 FormContext formContext = { formData.release() .leakRef(), length };489 FormContext formContext = { formData.release(), length }; 475 490 476 491 RetainPtr<CFReadStreamRef> stream(AdoptCF, wkCreateCustomCFReadStream(formCreate, formFinalize, … … 482 497 FormData* httpBodyFromStream(NSInputStream* stream) 483 498 { 484 return getStreamFormDataMap().get((CFReadStreamRef)stream).get(); 499 FormStreamFields* formStream = static_cast<FormStreamFields*>(NSMapGet(streamFieldsMap(), stream)); 500 if (!formStream) 501 return 0; 502 return formStream->formData.get(); 485 503 } 486 504
Note: See TracChangeset
for help on using the changeset viewer.