Details
-
Type:
Bug
-
Status: Closed
-
Priority:
Medium
-
Resolution: Done
-
Component/s: None
-
Labels:
Description
The current implementation of weak references has a race condition when multiple threads read the same weak reference to a deallocating object simultaneously. Since this is semantically read-only access (even if writing occurs under the hood), this should be made safe.
The bug itself lies in the swift_weakLoadStrong function. If two threads simultaneously enter this function with the same weak reference and object->refCount.isDeallocating() is true, the threads will race. This can result in calling swift_unownedRelease() twice resulting in a double-free or worse, or it could result in one thread calling swift_tryRetain() on a deallocated object.
Here is a test case which demonstrates the problem:
import Foundation class Target {} class WeakHolder { weak var weak: Target? } for i in 0..<1000000 { print(i) let holder = WeakHolder() holder.weak = Target() dispatch_async(dispatch_get_global_queue(0, 0), { let _ = holder.weak }) dispatch_async(dispatch_get_global_queue(0, 0), { let _ = holder.weak }) }
This is addressed in https://github.com/apple/swift/pull/1454