[PATCH] D53727: Only call FlushFileBuffers when writing executables
Alexandre Ganea via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 2 14:22:30 PDT 2018
aganea updated this revision to Diff 172433.
https://reviews.llvm.org/D53727
Files:
lib/Support/Windows/Path.inc
lib/Support/Windows/WindowsSupport.h
Index: lib/Support/Windows/WindowsSupport.h
===================================================================
--- lib/Support/Windows/WindowsSupport.h
+++ lib/Support/Windows/WindowsSupport.h
@@ -41,6 +41,7 @@
#include "llvm/Config/config.h" // Get build system configuration settings
#include "llvm/Support/Chrono.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/VersionTuple.h"
#include <cassert>
#include <string>
#include <system_error>
@@ -71,6 +72,40 @@
Mask) != FALSE;
}
+typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
+#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
+
+inline llvm::VersionTuple GetWindowsOSVersion() {
+ HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
+ if (hMod) {
+ auto getVer = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion");
+ if (getVer) {
+ RTL_OSVERSIONINFOEXW info{};
+ info.dwOSVersionInfoSize = sizeof(info);
+ if (getVer((PRTL_OSVERSIONINFOW)&info) == STATUS_SUCCESS) {
+ return llvm::VersionTuple(info.dwMajorVersion, info.dwMinorVersion, 0,
+ info.dwBuildNumber);
+ }
+ }
+ }
+
+ OSVERSIONINFOEX info;
+ ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
+ info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+#pragma warning(push)
+#pragma warning(disable : 4996)
+ // Starting with Microsoft SDK for Windows 8.1, this function is deprecated
+ // in favor of the new Windows Version Helper APIs. Since we don't specify a
+ // minimum SDK version, it's easier to simply disable the warning rather than
+ // try to support both APIs.
+ if (GetVersionEx((LPOSVERSIONINFO)&info) == 0)
+ return llvm::VersionTuple();
+#pragma warning(pop)
+
+ return llvm::VersionTuple(info.dwMajorVersion, info.dwMinorVersion, 0,
+ info.dwBuildNumber);
+}
+
inline bool MakeErrMsg(std::string *ErrMsg, const std::string &prefix) {
if (!ErrMsg)
return true;
Index: lib/Support/Windows/Path.inc
===================================================================
--- lib/Support/Windows/Path.inc
+++ lib/Support/Windows/Path.inc
@@ -854,16 +854,37 @@
Mapping = 0;
}
+static bool hasFlushBufferKernelBug() {
+ static bool Ret{GetWindowsOSVersion() < llvm::VersionTuple(10, 0, 0, 17763)};
+ return Ret;
+}
+
+static bool isEXE(StringRef Magic) {
+ static const char PEMagic[] = {'P', 'E', '\0', '\0'};
+ if (Magic.startswith(StringRef("MZ")) && Magic.size() >= 0x3c + 4) {
+ uint32_t off = read32le(Magic.data() + 0x3c);
+ // PE/COFF file, either EXE or DLL.
+ if (Magic.substr(off).startswith(StringRef(PEMagic, sizeof(PEMagic))))
+ return true;
+ }
+ return false;
+}
+
mapped_file_region::~mapped_file_region() {
if (Mapping) {
+
+ bool Exe = isEXE(StringRef((char *)Mapping, Size));
+
::UnmapViewOfFile(Mapping);
- if (Mode == mapmode::readwrite) {
+ if (Mode == mapmode::readwrite && 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);
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D53727.172433.patch
Type: text/x-patch
Size: 3528 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20181102/abc4eb27/attachment.bin>
More information about the llvm-commits
mailing list