Repository: bitcoin
Issue: Potential data race on fHavePruned flag
Labels: Bug,Block storage

<!-- This issue tracker is only for technical issues related to Bitcoin Core.

General bitcoin questions and/or support requests are best directed to the Bitcoin StackExchange at https://bitcoin.stackexchange.com.

For reporting security issues, please read instructions at https://bitcoincore.org/en/contact/.

If the node is "stuck" during sync or giving "block checksum mismatch" errors, please ensure your hardware is stable by running memtest and observe CPU temperature with a load-test tool such as linpack before creating an issue! -->

<!-- Describe the issue -->

We detected a potential race on the global variable [`fHavePruned`][fHavePruned] with a static data race detection tool.

Because the report is from a static analysis tool,  we do not have a concrete execution or trace, but we have reviewed the report and are reasonably confident this variable can be accessed in parallel and is not guarded by any common locks.

We are not able to confirm 100% that this race is real, or what impacts it may have on the program, but we decided to report it just to be safe.  

#### Writing Thread
The flag can be set to true by the thread spawned at [`init.cpp:1883`](https://github.com/bitcoin/bitcoin/blob/9be7fe4849310884294669b019dd8300f69bc334/src/init.cpp#L1883)

https://github.com/bitcoin/bitcoin/blob/9be7fe4849310884294669b019dd8300f69bc334/src/init.cpp#L1883-L1885

This thread can call [`ThreadImport`][ThreadImport] -> [`LoadExternalBlockFile`][LoadExternalBlockFile] -> [`AcceptBlock`][AcceptBlock] -> [`FlushStateToDisk`][FlushStateToDisk]

And the `FlushStateToDisk` function can write to the `fHavePruned` flag.

https://github.com/bitcoin/bitcoin/blob/9be7fe4849310884294669b019dd8300f69bc334/src/validation.cpp#L2311


[fHavePruned]: https://github.com/bitcoin/bitcoin/blob/9be7fe4849310884294669b019dd8300f69bc334/src/validation.cpp#L139
[ThreadImport]: https://github.com/bitcoin/bitcoin/blob/9be7fe4849310884294669b019dd8300f69bc334/src/init.cpp#L1884
[LoadExternalBlockFile]: https://github.com/bitcoin/bitcoin/blob/9be7fe4849310884294669b019dd8300f69bc334/src/init.cpp#L715
[AcceptBlock]: https://github.com/bitcoin/bitcoin/blob/9be7fe4849310884294669b019dd8300f69bc334/src/validation.cpp#L4717
[FlushStateToDisk]: https://github.com/bitcoin/bitcoin/blob/9be7fe4849310884294669b019dd8300f69bc334/src/validation.cpp#L3807

#### Reading Thread

The [`fHavePruned`][fHavePruned] flag can be read as part of the REST HTTP handler [`rest_block_extended`](https://github.com/bitcoin/bitcoin/blob/9be7fe4849310884294669b019dd8300f69bc334/src/rest.cpp#L300) which registered at [`rest.cpp:690`](
https://github.com/bitcoin/bitcoin/blob/9be7fe4849310884294669b019dd8300f69bc334/src/rest.cpp#L672-L693).

From there the handler can call [`rest_block`][rest_block] -> [`blockToJSON`][blockToJSON] -> [`IsBlockPruned`][isBlockPruned]

And `IsBlockPruned` will read `fHavePruned`

https://github.com/bitcoin/bitcoin/blob/9be7fe4849310884294669b019dd8300f69bc334/src/validation.h#L1026

[isBlockPruned]: https://github.com/bitcoin/bitcoin/blob/9be7fe4849310884294669b019dd8300f69bc334/src/rpc/blockchain.cpp#L167
[blockToJSON]: https://github.com/bitcoin/bitcoin/blob/9be7fe4849310884294669b019dd8300f69bc334/src/rest.cpp#L285
[rest_block]: https://github.com/bitcoin/bitcoin/blob/9be7fe4849310884294669b019dd8300f69bc334/src/rest.cpp#L300

**Expected behavior**

No threads reading and writing to the same variable without synchronization.

**Actual behavior**

It appears possible for threads to read and write [`fHavePruned`][fHavePruned] in parallel.

**To reproduce**

May be difficult to reproduce consistently as we found the potential race through static analysis and data races can be non-deterministic.

**System information**

We analyzed commit 328aaac80 specifically, but the issue is still present at the time of posting this issue. 

For reference, here is a screenshot of the report generated by our tool ([Coderrect Scanner](https://coderrect.com/overview/)). I have summarized all the info from this report above.
![Coderrect Scanner Report](https://user-images.githubusercontent.com/25114061/113774750-4f7deb80-96ed-11eb-98e1-b7553a82f001.png)