Concurrency bugs without brute-force reruns: an agent reads the semantics and finds 38 more in RaceBench
Lead
Reins turns an LLM agent's reasoning about concurrency semantics into scheduling constraints, triggering 769 of RaceBench's 1,500 injected bugs, 38 more than the best controlled-scheduling baseline, and finding six previously unknown concurrency bugs in Mozilla's NSPR and SpiderMonkey.
Story
Concurrency bugs surface only under particular thread interleavings, so Reins has an agent first work out which shared-variable accesses and synchronization operations go wrong under which interleaving, then steer thread scheduling toward those interleavings. Earlier controlled concurrency testing explored the interleaving space by systematic enumeration or randomized sampling with probabilistic guarantees, deciding at the level of events and executions without access to program semantics, so bugs with narrow triggering windows and specific state preconditions stayed hard to expose within a limited budget. Across the 75 targets and 1,500 injected bugs of RaceBench, Reins triggers 769, the highest of all tools and 38 more than the best baseline SURW at 731; on the 52 single-bug programs of SCTBench and ConVul, Reins detects 48 while SURW, RFF, PCT-3, PCT-10 and RW detect 46, 47, 44, 43 and 35.
The agent starts from shared-variable accesses observed in real executions, reads source code and queries static information as needed, and writes its conjecture as a schedule plan constraining only a few key event orders and variable values. A scheduler must decide which thread runs next at every scheduling point, and a single run may involve thousands of such points, so having the agent make every decision is impractical and its high-level semantic reasoning cannot be translated directly into concrete thread choices. The controlled scheduler prioritizes or delays threads only at the scheduling points the plan touches and decides the rest at random; the events and variables in a plan are validated against the program before execution, a bug-triggering run records its scheduling trace for deterministic replay, and a non-triggering run distinguishes whether the interleaving did not happen as planned or happened without the expected failure.
What to watch
The approach targets shared-memory multithreaded programs, starting from given test entries and inputs, and detects bugs only in the code those executions reach. It covers common concurrency bug patterns that produce observable failures such as crashes, assertion failures and hangs, including data races, atomicity violations, order violations and deadlocks. The evaluation spans three public benchmarks and two Mozilla projects, NSPR at about 136 kLOC and SpiderMonkey at about 1,214 kLOC.
The randomness of LLM output is the main source of uncertainty, since hypotheses and plans may differ across runs, and because each run is costly every tool and configuration was run once with a single model. RaceBench's injected bugs leave recognizable traces in the source code, which the authors mechanically anonymize by renaming identifiers and removing injection markers, but benchmark code may appear in the model's training corpus. No tool finds more than about 51% of the injected bugs within the 5-hour budget, partly because only the seed input is used while some injected bugs need the specific data in their mutated inputs.
