ThreadSanitizer
在以下运行的 Swift 程序中检测到数据竞争macOS
:
import Dispatch
class Foo<T> {
var value: T?
let queue = DispatchQueue(label: "Foo syncQueue")
init(){}
func complete(value: T) {
queue.sync {
self.value = value
}
}
static func completeAfter(_ delay: Double, value: T) -> Foo<T> {
let returnedFoo = Foo<T>()
let queue = DispatchQueue(label: "timerEventHandler")
let timer = DispatchSource.makeTimerSource(queue: queue)
timer.setEventHandler {
returnedFoo.complete(value: value)
timer.cancel()
}
timer.scheduleOneshot(deadline: .now() + delay)
timer.resume()
return returnedFoo
}
}
func testCompleteAfter() {
let foo = Foo<Int>.completeAfter(0.1, value: 1)
sleep(10)
}
testCompleteAfter()
在 iOS 模拟器上运行时,ThreadSanitizer 不会检测到竞态。
ThreadSanitizer 输出:
WARNING: ThreadSanitizer: data race (pid=71596)
Read of size 8 at 0x7d0c0000eb48 by thread T2:
#0 block_destroy_helper.5 main.swift (DispatchTimerSourceDataRace+0x0001000040fb)
#1 _Block_release <null>:38 (libsystem_blocks.dylib+0x000000000951)
Previous write of size 8 at 0x7d0c0000eb48 by main thread:
#0 block_copy_helper.4 main.swift (DispatchTimerSourceDataRace+0x0001000040b0)
#1 _Block_copy <null>:38 (libsystem_blocks.dylib+0x0000000008b2)
#2 testCompleteAfter() -> () main.swift:40 (DispatchTimerSourceDataRace+0x000100003981)
#3 main main.swift:44 (DispatchTimerSourceDataRace+0x000100002250)
Location is heap block of size 48 at 0x7d0c0000eb20 allocated by main thread:
#0 malloc <null>:144 (libclang_rt.tsan_osx_dynamic.dylib+0x00000004188a)
#1 _Block_copy <null>:38 (libsystem_blocks.dylib+0x000000000873)
#2 testCompleteAfter() -> () main.swift:40 (DispatchTimerSourceDataRace+0x000100003981)
#3 main main.swift:44 (DispatchTimerSourceDataRace+0x000100002250)
Thread T2 (tid=3107318, running) created by thread T-1
[failed to restore the stack]
SUMMARY: ThreadSanitizer: data race main.swift in block_destroy_helper.5
代码有什么可疑之处吗?