summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIlya Biryukov <ibiryukov@google.com>2018-12-03 15:21:49 +0000
committerIlya Biryukov <ibiryukov@google.com>2018-12-03 15:21:49 +0000
commit1712bc7640033853d491228b589e7394ff77be2c (patch)
treee72e1876e33d6bcb644f00e3e7c732ee5373b6bb
parentfb39916048fcb8f7a14f91f624179625f9cd02c9 (diff)
downloadbcm5719-llvm-1712bc7640033853d491228b589e7394ff77be2c.tar.gz
bcm5719-llvm-1712bc7640033853d491228b589e7394ff77be2c.zip
[clangd] Avoid memory-mapping files on Windows
Summary: Memory-mapping files on Windows leads to them being locked and prevents editors from saving changes to those files on disk. This is fine for the compiler, but not acceptable for an interactive tool like clangd. Therefore, we choose to avoid using memory-mapped files on Windows. Reviewers: hokein, kadircet Reviewed By: kadircet Subscribers: yvvan, zturner, nik, malaperle, mgorny, ioeric, MaskRay, jkorous, arphaman, cfe-commits Differential Revision: https://reviews.llvm.org/D55139 llvm-svn: 348147
-rw-r--r--clang-tools-extra/clangd/CMakeLists.txt1
-rw-r--r--clang-tools-extra/clangd/FSProvider.cpp85
-rw-r--r--clang-tools-extra/clangd/FSProvider.h4
3 files changed, 87 insertions, 3 deletions
diff --git a/clang-tools-extra/clangd/CMakeLists.txt b/clang-tools-extra/clangd/CMakeLists.txt
index 2c039109d60..39467bd567e 100644
--- a/clang-tools-extra/clangd/CMakeLists.txt
+++ b/clang-tools-extra/clangd/CMakeLists.txt
@@ -23,6 +23,7 @@ add_clang_library(clangDaemon
FindSymbols.cpp
FileDistance.cpp
FS.cpp
+ FSProvider.cpp
FuzzyMatch.cpp
GlobalCompilationDatabase.cpp
Headers.cpp
diff --git a/clang-tools-extra/clangd/FSProvider.cpp b/clang-tools-extra/clangd/FSProvider.cpp
new file mode 100644
index 00000000000..d94be5bb12c
--- /dev/null
+++ b/clang-tools-extra/clangd/FSProvider.cpp
@@ -0,0 +1,85 @@
+//===--- FSProvider.cpp - VFS provider for ClangdServer -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FSProvider.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/VirtualFileSystem.h"
+#include <memory>
+
+using namespace llvm;
+
+namespace clang {
+namespace clangd {
+
+namespace {
+/// Always opens files in the underlying filesystem as "volatile", meaning they
+/// won't be memory-mapped. This avoid locking the files on Windows.
+class VolatileFileSystem : public llvm::vfs::ProxyFileSystem {
+public:
+ explicit VolatileFileSystem(llvm::IntrusiveRefCntPtr<FileSystem> FS)
+ : ProxyFileSystem(std::move(FS)) {}
+
+ llvm::ErrorOr<std::unique_ptr<vfs::File>>
+ openFileForRead(const Twine &InPath) override {
+ SmallString<128> Path;
+ InPath.toVector(Path);
+
+ auto File = getUnderlyingFS().openFileForRead(Path);
+ if (!File)
+ return File;
+ // Try to guess preamble files, they can be memory-mapped even on Windows as
+ // clangd has exclusive access to those.
+ StringRef FileName = llvm::sys::path::filename(Path);
+ if (FileName.startswith("preamble-") && FileName.endswith(".pch"))
+ return File;
+ return std::unique_ptr<VolatileFile>(
+ new VolatileFile(std::move(*File)));
+ }
+
+private:
+ class VolatileFile : public vfs::File {
+ public:
+ VolatileFile(std::unique_ptr<vfs::File> Wrapped)
+ : Wrapped(std::move(Wrapped)) {
+ assert(this->Wrapped);
+ }
+
+ virtual llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+ getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
+ bool /*IsVolatile*/) override {
+ return Wrapped->getBuffer(Name, FileSize, RequiresNullTerminator,
+ /*IsVolatile=*/true);
+ }
+
+ llvm::ErrorOr<vfs::Status> status() override { return Wrapped->status(); }
+ llvm::ErrorOr<std::string> getName() override { return Wrapped->getName(); }
+ std::error_code close() override { return Wrapped->close(); }
+
+ private:
+ std::unique_ptr<File> Wrapped;
+ };
+};
+} // namespace
+
+llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
+clang::clangd::RealFileSystemProvider::getFileSystem() const {
+// Avoid using memory-mapped files on Windows, they cause file locking issues.
+// FIXME: Try to use a similar approach in Sema instead of relying on
+// propagation of the 'isVolatile' flag through all layers.
+#ifdef _WIN32
+ return new VolatileFSProvider(vfs::getRealFileSystem());
+#else
+ return vfs::getRealFileSystem();
+#endif
+}
+} // namespace clangd
+} // namespace clang
diff --git a/clang-tools-extra/clangd/FSProvider.h b/clang-tools-extra/clangd/FSProvider.h
index a39758aed8a..67d2ec1508b 100644
--- a/clang-tools-extra/clangd/FSProvider.h
+++ b/clang-tools-extra/clangd/FSProvider.h
@@ -33,9 +33,7 @@ class RealFileSystemProvider : public FileSystemProvider {
public:
// FIXME: returns the single real FS instance, which is not threadsafe.
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
- getFileSystem() const override {
- return llvm::vfs::getRealFileSystem();
- }
+ getFileSystem() const override;
};
} // namespace clangd
OpenPOWER on IntegriCloud