RealtimeSanitizer checks the promise that a function never blocks
There is a class of C++ function that must never block. An audio callback has a few milliseconds to fill a buffer before the speaker underruns. A control loop has a deadline set by physics. An interrupt handler has one set by the hardware. In all of them a correct answer delivered late is still a failure, and the usual causes are invisible in the source: a std::vector that quietly reallocates, a std::mutex that waits, a log line that touches the filesystem.
AddressSanitizer and friends cannot help here, because nothing is wrong in the memory-safety sense. The code is correct. It is just not allowed to do what it is doing.
RealtimeSanitizer (Clang, -fsanitize=realtime) checks exactly that. You mark a function with [[clang::nonblocking]], which is a promise that it will not call anything that might block, and RTSan verifies the promise at runtime with interposed allocator and locking primitives. A violation is reported the way ASan reports a bad access: a named error and a full stack.
The demo’s audio_callback is marked [[clang::nonblocking]] and does two ordinary things: a push_back on an empty vector and a lock_guard. Both are reported. The first is the interesting one, because nothing in the line buf.push_back(1.0f) looks like an allocation:
==1==ERROR: RealtimeSanitizer: unsafe-library-call
Intercepted call to real-time unsafe function `malloc` in real-time context!
#0 ... in malloc
#1 ... in operator new(unsigned long)
#2 ... in std::__new_allocator<float>::allocate(unsigned long, void const*)
...
#6 ... in std::vector<float>::_M_realloc_append<float>(float&&)
The stack walks from the intercepted malloc straight back to the push_back that caused it. That is the whole value proposition: the tool finds the allocation through six layers of standard-library inlining, in code where a human reviewer sees only a container append.
What it catches, and what it costs
RTSan interposes the things that block in practice: malloc and free and everything built on them, mutex operations, thread creation and joining, file and socket syscalls, and sleep. The annotation is part of Clang’s function-effects analysis, and it comes in two strengths: [[clang::nonblocking]] for “must not block” and [[clang::nonallocating]] for the narrower “must not allocate.”
Two practical notes. It is a Clang feature (the demo above runs on clang trunk, not GCC), and it is a runtime check, so it only reports the violations your test actually executes. That makes it a natural fit for the test suite from episode 1: run your realtime paths under RTSan in CI, and a newly introduced allocation fails a test instead of surfacing as an intermittent glitch a user reports months later.
The demo sets halt_on_error=false so it can keep running and exit cleanly in the browser. In a real build you want the default, which stops at the first violation.
The pattern so far
Each layer of a verification setup checks a different kind of promise. Unit tests check the cases you thought of. The sanitizers check that the language’s rules were not broken. RTSan checks a promise the type system has no way to express: not what this function computes, but what it is allowed to do on the way there.
Next in the series: what the compiler already tells you about performance, without running anything at all.
Sources: Clang RealtimeSanitizer documentation · Clang function effect analysis (nonblocking/nonallocating).