Skip to content

Fix sourcekitd persistent file-locks on Windows #75406

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 2 commits into from
Aug 1, 2024
Merged
Show file tree
Hide file tree
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
6 changes: 6 additions & 0 deletions include/swift/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,12 @@ namespace swift {
/// Enable verification when every SubstitutionMap is constructed.
bool VerifyAllSubstitutionMaps = false;

/// If set to true, the source manager will avoid memory mapping source files
/// with the expectation they may change on disk. This is most useful when
/// opening files under sourcekitd on Windows, as memory mapping on Windows
/// prevents files from being written.
bool OpenSourcesAsVolatile = false;

/// Load swiftmodule files in memory as volatile and avoid mmap.
bool EnableVolatileModules = false;

Expand Down
7 changes: 7 additions & 0 deletions include/swift/Basic/SourceManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ class SourceManager {
private:
llvm::SourceMgr LLVMSourceMgr;
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem;
bool OpenSourcesAsVolatile = false;
unsigned IDEInspectionTargetBufferID = 0U;
unsigned IDEInspectionTargetOffset;

Expand Down Expand Up @@ -166,6 +167,12 @@ class SourceManager {
return FileSystem;
}

// Setting this prevents SourceManager from memory mapping sources (via opening files
// with isVolatile=true);
void setOpenSourcesAsVolatile() {
OpenSourcesAsVolatile = true;
}

void setIDEInspectionTarget(unsigned BufferID, unsigned Offset) {
assert(BufferID != 0U && "Buffer should be valid");

Expand Down
6 changes: 5 additions & 1 deletion lib/Basic/SourceLoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,11 @@ unsigned SourceManager::getExternalSourceBufferID(StringRef Path) {
return It->getSecond();
}
unsigned Id = 0u;
auto InputFileOrErr = swift::vfs::getFileOrSTDIN(*getFileSystem(), Path);
auto InputFileOrErr =
swift::vfs::getFileOrSTDIN(*getFileSystem(), Path,
/* FileSize */ -1,
/* RequiresNullTerminator */ true,
/* isVolatile */ this->OpenSourcesAsVolatile);
if (InputFileOrErr) {
// This assertion ensures we can look up from the map in the future when
// using the same Path.
Expand Down
4 changes: 4 additions & 0 deletions lib/Frontend/Frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,10 @@ bool CompilerInstance::setup(const CompilerInvocation &Invoke,
Invocation.getSearchPathOptions().dump(LangOpts.Target.isOSDarwin());
}

if (LangOpts.OpenSourcesAsVolatile) {
this->getSourceMgr().setOpenSourcesAsVolatile();
}

// If we expect an implicit stdlib import, load in the standard library. If we
// either fail to find it or encounter an error while loading it, bail early. Continuing will at best
// trigger a bunch of other errors due to the stdlib being missing, or at
Expand Down
5 changes: 5 additions & 0 deletions lib/IDETool/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,11 @@ bool ide::initCompilerInvocation(
LangOpts.AttachCommentsToDecls = true;
LangOpts.DiagnosticsEditorMode = true;
LangOpts.CollectParsedToken = true;
#if defined(_WIN32)
// Source files that might be open in an editor should not be memory mapped on Windows,
// as they will become read-only.
LangOpts.OpenSourcesAsVolatile = true;
#endif
if (LangOpts.PlaygroundTransform) {
// The playground instrumenter changes the AST in ways that disrupt the
// SourceKit functionality. Since we don't need the instrumenter, and all we
Expand Down