Skip to content

[Support] Avoid a VirtualBox shared folders mmap bug #78597

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 23, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions llvm/lib/Support/Windows/Path.inc
Original file line number Diff line number Diff line change
Expand Up @@ -959,15 +959,36 @@ void mapped_file_region::unmapImpl() {

::UnmapViewOfFile(Mapping);

if (Mode == mapmode::readwrite && Exe && hasFlushBufferKernelBug()) {
if (Mode == mapmode::readwrite) {
bool DoFlush = Exe && hasFlushBufferKernelBug();
// There is a Windows kernel bug, the exact trigger conditions of which
// are not well understood. When triggered, dirty pages are not properly
// flushed and subsequent process's attempts to read a file can return
// invalid data. Calling FlushFileBuffers on the write handle is
// sufficient to ensure that this bug is not triggered.
// The bug only occurs when writing an executable and executing it right
// after, under high I/O pressure.
::FlushFileBuffers(FileHandle);
if (!DoFlush) {
// Separately, on VirtualBox Shared Folder mounts, writes via memory
// maps always end up unflushed (regardless of version of Windows),
// unless flushed with this explicit call, if they are renamed with
// SetFileInformationByHandle(FileRenameInfo) before closing the output
// handle.
//
// As the flushing is quite expensive, use a heuristic to limit the
// cases where we do the flushing. Only do the flushing if we aren't
// sure we are on a local file system.
bool IsLocal = false;
SmallVector<wchar_t, 128> FinalPath;
if (!realPathFromHandle(FileHandle, FinalPath)) {
// Not checking the return value here - if the check fails, assume the
// file isn't local.
is_local_internal(FinalPath, IsLocal);
}
DoFlush = !IsLocal;
}
if (DoFlush)
::FlushFileBuffers(FileHandle);
}

::CloseHandle(FileHandle);
Expand Down