Changeset 122494 in webkit
- Timestamp:
- Jul 12, 2012 12:59:23 PM (12 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r122489 r122494 1 2012-07-12 Gavin Barraclough <barraclough@apple.com> 2 3 Threadsafety issues in WebScriptObject 4 https://bugs.webkit.org/show_bug.cgi?id=90849 5 6 Reviewed by Filip Pizlo & Oliver Hunt. 7 8 Updated fix for this bug. Taking the JSC API lock from WebScriptObject::release 9 may not be safe; better to just guard the JSWrapperCache with its own spinlock. 10 11 * bindings/objc/WebScriptObject.mm: 12 (WebCore::getJSWrapper): 13 - Added spinlock; also retain/autorelease the returned wrapper - it is unsafe 14 to wait for the caller to do so, due to a race condition vs release removing 15 the wrapper from the map. 16 (WebCore::addJSWrapper): 17 - Take the spinlock guarding the cache. 18 (WebCore::removeJSWrapper): 19 - Take the spinlock guarding the cache. 20 (WebCore::removeJSWrapperIfRetainCountOne): 21 - Take the spinlock guarding the cache, remove the wrapper if retainCount is one. 22 (WebCore::createJSWrapper): 23 - Remove the API lock; this method no longer needs to retain/autorelease (this is 24 done by getJSWrapper). 25 (-[WebScriptObject _setImp:originRootObject:rootObject:]): 26 - Remove the API lock. 27 (-[WebScriptObject release]): 28 - Remove the API lock, retainCount check moved into removeJSWrapperIfRetainCountOne. 29 1 30 2012-07-11 David Hyatt <hyatt@apple.com> 2 31 -
trunk/Source/WebCore/bindings/objc/WebScriptObject.mm
r122198 r122494 51 51 #import <runtime/Completion.h> 52 52 #import <runtime/Completion.h> 53 #import <wtf/TCSpinLock.h> 53 54 #import <wtf/Threading.h> 54 55 … … 61 62 62 63 static NSMapTable* JSWrapperCache; 64 static SpinLock spinLock = SPINLOCK_INITIALIZER; 63 65 64 66 NSObject* getJSWrapper(JSObject* impl) 65 67 { 68 ASSERT(isMainThread()); 69 SpinLockHolder holder(&spinLock); 70 66 71 if (!JSWrapperCache) 67 72 return nil; 68 return static_cast<NSObject*>(NSMapGet(JSWrapperCache, impl)); 73 NSObject* wrapper = static_cast<NSObject*>(NSMapGet(JSWrapperCache, impl)); 74 return wrapper ? [[wrapper retain] autorelease] : nil; 69 75 } 70 76 71 77 void addJSWrapper(NSObject* wrapper, JSObject* impl) 72 78 { 79 ASSERT(isMainThread()); 80 SpinLockHolder holder(&spinLock); 81 73 82 if (!JSWrapperCache) 74 83 JSWrapperCache = createWrapperCache(); … … 78 87 void removeJSWrapper(JSObject* impl) 79 88 { 89 SpinLockHolder holder(&spinLock); 90 80 91 if (!JSWrapperCache) 81 92 return; … … 83 94 } 84 95 96 static void removeJSWrapperIfRetainCountOne(NSObject* wrapper, JSObject* impl) 97 { 98 SpinLockHolder holder(&spinLock); 99 100 if (!JSWrapperCache) 101 return; 102 if ([wrapper retainCount] == 1) 103 NSMapRemove(JSWrapperCache, impl); 104 } 105 85 106 id createJSWrapper(JSC::JSObject* object, PassRefPtr<JSC::Bindings::RootObject> origin, PassRefPtr<JSC::Bindings::RootObject> root) 86 107 { 87 // NSMap is not thread safe, hold the JSC API lock; also synchronize this vs. release.88 JSC::JSLockHolder holder(JSDOMWindowBase::commonJSGlobalData());89 90 108 if (id wrapper = getJSWrapper(object)) 91 return [[wrapper retain] autorelease];109 return wrapper; 92 110 return [[[WebScriptObject alloc] _initWithJSObject:object originRootObject:origin rootObject:root] autorelease]; 93 111 } … … 149 167 _private->originRootObject = originRootObject.leakRef(); 150 168 151 // NSMap is not thread safe, hold the JSC API lock.152 JSC::JSLockHolder holder(JSDOMWindowBase::commonJSGlobalData());153 154 169 WebCore::addJSWrapper(self, imp); 155 170 … … 232 247 - (oneway void)release 233 248 { 234 { 235 // NSMap is not thread safe, hold the JSC API lock; also synchronize this vs. getJSWrapper. 236 JSC::JSLockHolder holder(JSDOMWindowBase::commonJSGlobalData()); 237 238 // If we're releasing the last reference to this object, remove if from the map, 239 // this will prevent this object from being returned by getJSWrapper. 240 if (_private->imp && [self retainCount] == 1) 241 WebCore::removeJSWrapper(_private->imp); 242 } 249 // If we're releasing the last reference to this object, remove if from the map. 250 if (_private->imp) 251 WebCore::removeJSWrapperIfRetainCountOne(self, _private->imp); 243 252 244 253 [super release];
Note: See TracChangeset
for help on using the changeset viewer.