[Support] Avoid a VirtualBox shared folders mmap bug (#78597)
commit7ec078ed4b7f6e7f44133a2abbc35c74b67787cc
authorMartin Storsjö <martin@martin.st>
Tue, 23 Jan 2024 11:39:48 +0000 (23 13:39 +0200)
committerGitHub <noreply@github.com>
Tue, 23 Jan 2024 11:39:48 +0000 (23 13:39 +0200)
tree2f304485e8f62e44e4f379e46d31f6a02a000297
parent33ec6b3de7f72bc5da6351538f713777c1f8a199
[Support] Avoid a VirtualBox shared folders mmap bug (#78597)

In acd8791c2619f2afc0347c1bff073b32fbffb5d6, a call to FlushFileBuffers
was added to work around a rare kernel bug. In
3b9b4d2156673edda50584086fbfb0d66460b4d2, the scope of that workaround
was limited, for performance reasons, as the flushes are quite
expensive.

On VirtualBox shared folders, closing a memory mapping that has been
written to, also needs to be explicitly flushed, if renaming the output
file before it is closed. Contrary to the kernel bug, this always
happens on such mounts. In these cases, the output ends up as a file of
the right size, but the contents are all zeros.

The sequence to trigger the issue on the VirtualBox Shared Folders is
this, summarized:

    file = CreateFile()
    mapping = CreateFileMapping(file)
    mem = MapViewOfFile()
    CloseHandle(mapping)
    write(mem)
    UnmapViewOfFile(mem)
    SetFileInformationByHandle(file, FileRenameInfo)
    CloseHandle(file)

With this sequence, the output file always ends up with all zeros. See
https://github.com/mstorsjo/llvm-mingw/issues/393 for a full
reproduction example.

To avoid this issue, call FlushFileBuffers() when the file may reside on
a VitualBox shared folder. As the flushes are expensive, only do them
when the output isn't on a local file system.

The issue with VirtualBox shared folders could also be fixed by calling
FlushViewOfFile before UnmapViewOfFile, and doing that could be slightly
less expensive than FlushFileBuffers.

Empirically, the difference between the two is very small though, and as
it's not easy to verify whether switching FlushFileBuffers to
FlushViewOfFile helps with the rare kernel bug, keep using
FlushFileBuffers for both cases, for code simplicity.

This fixes downstream bug
https://github.com/mstorsjo/llvm-mingw/issues/393.
llvm/lib/Support/Windows/Path.inc