On Windows we've observed that if you open a file,
write to it, map it into memory and close the file handle, the
contents of the memory mapping can sometimes be incorrect. That
was what we did when adding an entry to the ThinLTO cache using the
TempFile and MemoryBuffer classes, and it was causing intermittent
build failures on Chromium's ThinLTO bots on Windows. More details
are in the associated Chromium bug (crbug.com/786127).
We can prevent this from happening by keeping a handle to the
file open while the mapping is active. So this patch changes the
mapped_file_region class to duplicate the file handle when mapping
the file and close it upon unmapping it.
One gotcha is that the file handle that we keep open must not have
been created with FILE_FLAG_DELETE_ON_CLOSE, as otherwise the operating
system will prevent other processes from opening the file. We can achieve
this by avoiding the use of FILE_FLAG_DELETE_ON_CLOSE altogether.
Instead, we use SetFileInformationByHandle with FileDispositionInfo to manage
the delete-on-close bit. This lets us remove the hack that we used to use to clear
the delete-on-close bit on a file opened with FILE_FLAG_DELETE_ON_CLOSE.
A downside of using SetFileInformationByHandle/FileDispositionInfo as opposed
to FILE_FLAG_DELETE_ON_CLOSE is that it prevents us from using CreateFile to open
the file while the flag is set, even within the same process. This doesn't seem to matter
for almost every client of TempFile, except for LockFileManager, which calls sys::fs::create_link
to create a hard link from the lock file, and in the process of doing so tries to open the
file. To prevent this change from breaking LockFileManager I changed it to stop using
TempFile by effectively reverting r318550.