diff --git a/llvm/lib/Support/Caching.cpp b/llvm/lib/Support/Caching.cpp index 52fd0ba7d681c..05dd6a594a8bc 100644 --- a/llvm/lib/Support/Caching.cpp +++ b/llvm/lib/Support/Caching.cpp @@ -37,6 +37,8 @@ Expected llvm::localCache(const Twine &CacheNameRef, TempFilePrefixRef.toVector(TempFilePrefix); CacheDirectoryPathRef.toVector(CacheDirectoryPath); + bool OnNFS = !sys::fs::is_local(CacheDirectoryPath); + auto Func = [=](unsigned Task, StringRef Key, const Twine &ModuleName) -> Expected { // This choice of file name allows the cache to be pruned (see pruneCache() @@ -52,7 +54,8 @@ Expected llvm::localCache(const Twine &CacheNameRef, ErrorOr> MBOrErr = MemoryBuffer::getOpenFile(*FDOrErr, EntryPath, /*FileSize=*/-1, - /*RequiresNullTerminator=*/false); + /*RequiresNullTerminator=*/false, + /*IsVolatile=*/OnNFS); sys::fs::closeFile(*FDOrErr); if (MBOrErr) { AddBuffer(Task, ModuleName, std::move(*MBOrErr)); diff --git a/llvm/lib/Support/MemoryBuffer.cpp b/llvm/lib/Support/MemoryBuffer.cpp index 9c49c143cf01c..470538276c98b 100644 --- a/llvm/lib/Support/MemoryBuffer.cpp +++ b/llvm/lib/Support/MemoryBuffer.cpp @@ -377,6 +377,21 @@ static bool shouldUseMmap(sys::fs::file_t FD, return false; #endif + // Do not use mmap on NFS file systems (IsVolatile is true). + // IsVolatile=true should be used on NFS file systems or when the files are + // expected to change (this happens on clangd when reading user's code). + // Otherwise, accessing the buffer obtained through mmap may result in a + // SIGBUS. Doing regular read() may result in "Stale file handle" errors, + // which is also not great, but at least `getOpenFileImpl` can forward the + // error to the user. In contrast, the SIGBUS happens on the caller's code and + // we cannot prevent it. + // + // FIXME: We could use the `CrashRecoveryContext`, and read one byte from + // every page of the file to catch the SIGBUS in advance. ATM I haven't + // managed to make this work, thus the conservative solution. + if (IsVolatile) + return false; + // mmap may leave the buffer without null terminator if the file size changed // by the time the last page is mapped in, so avoid it if the file size is // likely to change.