Case Study: The Thread Pool Passed 64/64 Tasks. ThreadSanitizer Found the Race in the Destructor

The thread pool passed every functional test on the first run: 64 tasks enqueued, 64 results returned, clean exit. ThreadSanitizer found a data race in the destructor on the same run. The writer was a free model; the reviewer was a sanitizer on a free server; the bug was a missing lock scope that no functional test could see.

Background

The project was a small batch hashing tool: walk a directory, compute SHA-256 for every file, write a manifest. The hashing is embarrassingly parallel, so the only interesting component was the worker pool. I generated the pool with a free model and verified it with the same pipeline I use for my own code: warnings on, functional tests, then sanitizers.

I used MonkeyCode's free model endpoint to generate the pool and its free server option to run the sanitizer builds. Disclosure: This article was prepared as part of MonkeyCode's product outreach. The workflow does not depend on either product; the commands below run on any Linux box with clang.