Description
Previous ID | SR-192 |
Radar | None |
Original Reporter | @mikeash |
Type | Bug |
Status | Closed |
Resolution | Done |
Additional Detail from JIRA
Votes | 8 |
Component/s | |
Labels | Bug, Runtime |
Assignee | @glessard |
Priority | Medium |
md5: e84790d9452452d03d108981ba9ce226
Issue 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
})
}