Article

Thread Sanitizer

Audit threading issues in your code.

Overview

The Thread Sanitizer, or TSan, is an LLVM based tool for Swift and C languages that detects data races at runtime. Data races occur when multiple threads access the same memory without synchronization and at least one access is a write. Data races are dangerous because they can cause programs to behave unpredictably, or even result in memory corruption.

TSan also detects other threading bugs, including uninitialized mutexes and thread leaks.

How TSan Works

The Thread Sanitizer records the information about each memory access, and checks whether that access participates in a race. All memory accesses in the code is transformed by the compiler in the following way:

Listing 1

Pseudocode for Thread Sanitizer memory access

// Before
*address = ...;  // or: ... = *address;
// After
RecordAndCheckWrite(address);
*address = ...;  // or: ... = *address;

Each thread stores its own timestamp and the timestamps for other threads in order to establish points of synchronization. Timestamps are incremented each time memory is accessed. By checking for consistency of memory access across threads, data races can be detected independent of the actual timing of the access. Therefore, the Thread Sanitizer can detect races even if they didn't manifest during a particular run.

Performance Impact

Running your code with Thread Sanitizer checks enabled can result in CPU slowdown of 2⨉ to 20⨉, and an increase in memory usage by 5⨉ to 10⨉. You can improve memory utilization and CPU overhead by compiling at the -O1 optimization level.

Topics

First Steps

Enabling the Thread Sanitizer

Configure your Xcode scheme to check for threading issues at runtime.

Thread Sanitizer Checks

Data Races

Detects unsynchronized access to mutable state across multiple threads.

Swift Access Races

Detects when multiple threads call a mutating method on the same structure, or pass a shared variable as inout without synchronization.

Races on Collections and Other APIs

Detects when a thread accesses a mutable object while another thread writes to that object, causing a data race.

Uninitialized Mutexes

Detects when a mutex is used before it's initialized.

Thread Leaks

Detects when threads aren't closed after use.

See Also

Threading

Main Thread Checker

Detect invalid use of AppKit, UIKit, and other APIs from a background thread.