Potentially fixed #17161.
It seems there’s a race in ReadBlockFromDisk and UndoReadFromDisk where after the block/undo file position is retrieved the actual block/undo file could be removed during prune. This could just cause the read to fail, or it could prevent the file from being removed if the file is already open depending on the platform (https://en.cppreference.com/w/cpp/io/c/remove). This PR uses a shared mutex to lock the removal of files until any reads are completed. This way it doesn’t block cs_main while reading so ReadBlockFromDisk usage can be moved outside of cs_main in some cases like #26308.
The first commit also updates the function signature of ReadRawBlockFromDisk to take a block index instead of the file position, and then the file position is retrieved while locking cs_main inside the function. That way it unifies it with ReadBlockFromDisk and can be moved outside cs_main scope inside net_processing in a follow up PR like #26326.
Also see #25232.