TSAN with Task/Concurrency warnings

@Jon_Shier - I stumbled over your gist Alamofire Test Thread Sanitizer Issues · GitHub outlining TSAN warnings with Alamofire - did you ever come to a conclusion of whether it's a real issue or something missing from TSAN?

I just got the very similar:

Test Suite 'TransactionTests' started at 2022-06-02 14:13:14.869
Test Case '-[StorageTests.TransactionTests testDatabaseConcurrentTransactionCommit]' started.
==================
WARNING: ThreadSanitizer: data race (pid=99440)
  Read of size 8 at 0x00010980dcc0 by thread T3:
    #0 (1) suspend resume partial function for closure #1 in closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit() TransactionTests.swift (swift-storagePackageTests:arm64+0x7a7b0)
    #1 swift::runJobInEstablishedExecutorContext(swift::Job*) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x3a534)

  Previous write of size 8 at 0x00010980dcc0 by thread T1:
    #0 closure #1 in closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit() TransactionTests.swift:85 (swift-storagePackageTests:arm64+0x7a708)
    #1 swift::runJobInEstablishedExecutorContext(swift::Job*) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x3a534)

  Location is heap block of size 1032 at 0x00010980dc00 allocated by thread T3:
    #0 malloc <null>:41088324 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x592cc)
    #1 swift::StackAllocator<1000ul, &(swift::TaskAllocatorSlabMetadata)>::getSlabForAllocation(unsigned long) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x408dc)
    #2 closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit() TransactionTests.swift:84 (swift-storagePackageTests:arm64+0x7a2b8)
    #3 swift::runJobInEstablishedExecutorContext(swift::Job*) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x3a534)

  Thread T3 (tid=15489003, running) is a GCD worker thread

  Thread T1 (tid=15489001, running) is a GCD worker thread

SUMMARY: ThreadSanitizer: data race TransactionTests.swift in (1) suspend resume partial function for closure #1 in closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit()
==================
==================
WARNING: ThreadSanitizer: data race (pid=99440)
  Read of size 8 at 0x00010980dcb8 by thread T3:
    #0 (1) suspend resume partial function for closure #1 in closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit() TransactionTests.swift (swift-storagePackageTests:arm64+0x7a7c4)
    #1 swift::runJobInEstablishedExecutorContext(swift::Job*) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x3a534)

  Previous write of size 8 at 0x00010980dcb8 by thread T1:
    #0 closure #1 in closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit() TransactionTests.swift (swift-storagePackageTests:arm64+0x7a680)
    #1 swift::runJobInEstablishedExecutorContext(swift::Job*) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x3a534)

  Location is heap block of size 1032 at 0x00010980dc00 allocated by thread T3:
    #0 malloc <null>:41088324 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x592cc)
    #1 swift::StackAllocator<1000ul, &(swift::TaskAllocatorSlabMetadata)>::getSlabForAllocation(unsigned long) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x408dc)
    #2 closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit() TransactionTests.swift:84 (swift-storagePackageTests:arm64+0x7a2b8)
    #3 swift::runJobInEstablishedExecutorContext(swift::Job*) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x3a534)

  Thread T3 (tid=15489003, running) is a GCD worker thread

  Thread T1 (tid=15489001, running) is a GCD worker thread

SUMMARY: ThreadSanitizer: data race TransactionTests.swift in (1) suspend resume partial function for closure #1 in closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit()
==================
==================
WARNING: ThreadSanitizer: data race (pid=99440)
  Read of size 8 at 0x00010980dca0 by thread T3:
    #0 (1) suspend resume partial function for closure #1 in closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit() TransactionTests.swift (swift-storagePackageTests:arm64+0x7a7d8)
    #1 swift::runJobInEstablishedExecutorContext(swift::Job*) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x3a534)

  Previous write of size 8 at 0x00010980dca0 by thread T1:
    #0 closure #1 in closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit() TransactionTests.swift (swift-storagePackageTests:arm64+0x7a58c)
    #1 swift::runJobInEstablishedExecutorContext(swift::Job*) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x3a534)

  Location is heap block of size 1032 at 0x00010980dc00 allocated by thread T3:
    #0 malloc <null>:41088324 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x592cc)
    #1 swift::StackAllocator<1000ul, &(swift::TaskAllocatorSlabMetadata)>::getSlabForAllocation(unsigned long) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x408dc)
    #2 closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit() TransactionTests.swift:84 (swift-storagePackageTests:arm64+0x7a2b8)
    #3 swift::runJobInEstablishedExecutorContext(swift::Job*) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x3a534)

  Thread T3 (tid=15489003, running) is a GCD worker thread

  Thread T1 (tid=15489001, running) is a GCD worker thread

SUMMARY: ThreadSanitizer: data race TransactionTests.swift in (1) suspend resume partial function for closure #1 in closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit()
==================
==================
WARNING: ThreadSanitizer: data race (pid=99440)
  Write of size 8 at 0x00010980dc88 by thread T3:
    #0 (1) suspend resume partial function for closure #1 in closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit() TransactionTests.swift:85 (swift-storagePackageTests:arm64+0x7a7fc)
    #1 swift::runJobInEstablishedExecutorContext(swift::Job*) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x3a534)

  Previous write of size 8 at 0x00010980dc88 by thread T1:
    #0 closure #1 in closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit() TransactionTests.swift (swift-storagePackageTests:arm64+0x7a5a0)
    #1 swift::runJobInEstablishedExecutorContext(swift::Job*) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x3a534)

  Location is heap block of size 1032 at 0x00010980dc00 allocated by thread T3:
    #0 malloc <null>:41088324 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x592cc)
    #1 swift::StackAllocator<1000ul, &(swift::TaskAllocatorSlabMetadata)>::getSlabForAllocation(unsigned long) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x408dc)
    #2 closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit() TransactionTests.swift:84 (swift-storagePackageTests:arm64+0x7a2b8)
    #3 swift::runJobInEstablishedExecutorContext(swift::Job*) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x3a534)

  Thread T3 (tid=15489003, running) is a GCD worker thread

  Thread T1 (tid=15489001, running) is a GCD worker thread

SUMMARY: ThreadSanitizer: data race TransactionTests.swift:85 in (1) suspend resume partial function for closure #1 in closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit()
==================
==================
WARNING: ThreadSanitizer: data race (pid=99440)
  Read of size 8 at 0x00010980dcb0 by thread T3:
    #0 (1) suspend resume partial function for closure #1 in closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit() TransactionTests.swift:95 (swift-storagePackageTests:arm64+0x7a874)
    #1 swift::runJobInEstablishedExecutorContext(swift::Job*) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x3a534)

  Previous write of size 8 at 0x00010980dcb0 by thread T1:
    #0 closure #1 in closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit() TransactionTests.swift (swift-storagePackageTests:arm64+0x7a564)
    #1 swift::runJobInEstablishedExecutorContext(swift::Job*) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x3a534)

  Location is heap block of size 1032 at 0x00010980dc00 allocated by thread T3:
    #0 malloc <null>:41088324 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x592cc)
    #1 swift::StackAllocator<1000ul, &(swift::TaskAllocatorSlabMetadata)>::getSlabForAllocation(unsigned long) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x408dc)
    #2 closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit() TransactionTests.swift:84 (swift-storagePackageTests:arm64+0x7a2b8)
    #3 swift::runJobInEstablishedExecutorContext(swift::Job*) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x3a534)

  Thread T3 (tid=15489003, running) is a GCD worker thread

  Thread T1 (tid=15489001, running) is a GCD worker thread

SUMMARY: ThreadSanitizer: data race TransactionTests.swift:95 in (1) suspend resume partial function for closure #1 in closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit()
==================
==================
WARNING: ThreadSanitizer: data race (pid=99440)
  Read of size 8 at 0x00010980dca8 by thread T3:
    #0 (1) suspend resume partial function for closure #1 in closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit() TransactionTests.swift:95 (swift-storagePackageTests:arm64+0x7a888)
    #1 swift::runJobInEstablishedExecutorContext(swift::Job*) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x3a534)

  Previous write of size 8 at 0x00010980dca8 by thread T1:
    #0 closure #1 in closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit() TransactionTests.swift (swift-storagePackageTests:arm64+0x7a578)
    #1 swift::runJobInEstablishedExecutorContext(swift::Job*) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x3a534)

  Location is heap block of size 1032 at 0x00010980dc00 allocated by thread T3:
    #0 malloc <null>:41088324 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x592cc)
    #1 swift::StackAllocator<1000ul, &(swift::TaskAllocatorSlabMetadata)>::getSlabForAllocation(unsigned long) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x408dc)
    #2 closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit() TransactionTests.swift:84 (swift-storagePackageTests:arm64+0x7a2b8)
    #3 swift::runJobInEstablishedExecutorContext(swift::Job*) <null>:41088324 (libswift_Concurrency.dylib:arm64e+0x3a534)

  Thread T3 (tid=15489003, running) is a GCD worker thread

  Thread T1 (tid=15489001, running) is a GCD worker thread

SUMMARY: ThreadSanitizer: data race TransactionTests.swift:95 in (1) suspend resume partial function for closure #1 in closure #1 in TransactionTests.testDatabaseConcurrentTransactionCommit()
==================
Test Case '-[StorageTests.TransactionTests testDatabaseConcurrentTransactionCommit]' passed (0.622 seconds).

and am a bit stumped as of root cause.

The concurrency runtime still does not support tsan and even the most trivial things give false-positive warnings.

1 Like

As @tgoyne said, TSAN simply doesn't support the concurrency feature and so doesn't understand what's safe and what's not. Hopefully we finally get support next week.

1 Like

Thanks both, do you know if there have been radar/feedback/issues filed for it so they are aware?

Short note for future googlers: Short update is that with Xcode 14 & Swift 5.7 dev toolchain just released it goes through clean now!

4 Likes