Skip to content

Instantly share code, notes, and snippets.

@Verdagon
Created November 29, 2025 03:45
Show Gist options
  • Select an option

  • Save Verdagon/2c2653de41534d96bdf93454cc7aa97e to your computer and use it in GitHub Desktop.

Select an option

Save Verdagon/2c2653de41534d96bdf93454cc7aa97e to your computer and use it in GitHub Desktop.
import Foundation
class Engine {
var fuel = 100
}
class Spaceship {
var engine = Engine()
}
func accelerate(_ ship: Spaceship) {
let engine = ship.engine // Race: read
// literally no field access
_ = engine // silence unused variable warning
}
func replaceEngine(_ ship: Spaceship) {
ship.engine = Engine() // Race: write
}
let ship = Spaceship()
let group = DispatchGroup()
let t1 = Thread {
for _ in 0..<1_000_000 {
accelerate(ship)
}
group.leave()
}
let t2 = Thread {
for _ in 0..<1_000_000 {
replaceEngine(ship)
}
group.leave()
}
group.enter()
group.enter()
t1.start()
t2.start()
group.wait()
print("Done")
// verdagon@Evans-MacBook-Pro swiftthread % swiftc -sanitize=thread main.swift -o main_tsan && ./main_tsan
// main_tsan(14565,0x1fd2d7ac0) malloc: nano zone abandoned due to inability to reserve vm space.
// ==================
// WARNING: ThreadSanitizer: data race (pid=14565)
// Write of size 8 at 0x0001055027b0 by thread T2:
// #0 Spaceship.engine.setter <null> (main_tsan:arm64+0x100003190)
// #1 replaceEngine(_:) <null> (main_tsan:arm64+0x100002bc8)
// #2 closure #2 in <null> (main_tsan:arm64+0x100002b20)
// #3 thunk for @escaping @callee_guaranteed @Sendable () -> () <null> (main_tsan:arm64+0x100003568)
// #4 __NSThread__start__ <null> (Foundation:arm64+0x5451c)
//
// Previous read of size 8 at 0x0001055027b0 by thread T1:
// #0 Spaceship.engine.getter <null> (main_tsan:arm64+0x10000310c)
// #1 accelerate(_:) <null> (main_tsan:arm64+0x10000291c)
// #2 closure #1 in <null> (main_tsan:arm64+0x100002880)
// #3 thunk for @escaping @callee_guaranteed @Sendable () -> () <null> (main_tsan:arm64+0x100003568)
// #4 __NSThread__start__ <null> (Foundation:arm64+0x5451c)
//
// Location is heap block of size 24 at 0x0001055027a0 allocated by main thread:
// #0 malloc <null> (libclang_rt.tsan_osx_dynamic.dylib:arm64+0x611e4)
// #1 swift_slowAlloc <null> (libswiftCore.dylib:arm64+0x3aa4c8)
// #2 main <null> (main_tsan:arm64+0x100002310)
//
// Thread T2 (tid=456766, running) created by main thread at:
// #0 pthread_create <null> (libclang_rt.tsan_osx_dynamic.dylib:arm64+0x31764)
// #1 -[NSThread startAndReturnError:] <null> (Foundation:arm64+0x7ce610)
// #2 <null> <null> (0x0001952420e0)
//
// Thread T1 (tid=456765, running) created by main thread at:
// #0 pthread_create <null> (libclang_rt.tsan_osx_dynamic.dylib:arm64+0x31764)
// #1 -[NSThread startAndReturnError:] <null> (Foundation:arm64+0x7ce610)
// #2 <null> <null> (0x0001952420e0)
//
// SUMMARY: ThreadSanitizer: data race (main_tsan:arm64+0x100003190) in Spaceship.engine.setter+0x58
// ==================
// Object 0x105504500 of class Engine deallocated with non-zero retain count 2. This object's deinit, or something called from it, may have created a strong reference to self which outlived deinit, resulting in a dangling reference.
// zsh: abort ./main_tsan
// verdagon@Evans-MacBook-Pro swiftthread %
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment