Skip to content

[stable/20221013] Proper fix for race in ClangdServer shutdown #5938

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
Jan 9, 2023
Merged
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
26 changes: 16 additions & 10 deletions clang-tools-extra/clangd/ClangdServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,27 +63,36 @@ struct UpdateIndexCallbacks : public ParsingCallbacks {
ClangdServer::Callbacks *ServerCallbacks,
const ThreadsafeFS &TFS, AsyncTaskRunner *Tasks)
: FIndex(FIndex), ServerCallbacks(ServerCallbacks), TFS(TFS),
Tasks(Tasks) {}
Stdlib{std::make_shared<StdLibSet>()}, Tasks(Tasks) {}

void onPreambleAST(PathRef Path, llvm::StringRef Version,
const CompilerInvocation &CI, ASTContext &Ctx,
Preprocessor &PP,
const CanonicalIncludes &CanonIncludes) override {
// If this preamble uses a standard library we haven't seen yet, index it.
if (FIndex)
if (auto Loc = Stdlib.add(*CI.getLangOpts(), PP.getHeaderSearchInfo()))
if (auto Loc = Stdlib->add(*CI.getLangOpts(), PP.getHeaderSearchInfo()))
indexStdlib(CI, std::move(*Loc));

if (FIndex)
FIndex->updatePreamble(Path, Version, Ctx, PP, CanonIncludes);
}

void indexStdlib(const CompilerInvocation &CI, StdLibLocation Loc) {
auto Task = [this, LO(*CI.getLangOpts()), Loc(std::move(Loc)),
CI(std::make_unique<CompilerInvocation>(CI))]() mutable {
// This task is owned by Tasks, which outlives the TUScheduler and
// therefore the UpdateIndexCallbacks.
// We must be careful that the references we capture outlive TUScheduler.
auto Task = [LO(*CI.getLangOpts()), Loc(std::move(Loc)),
CI(std::make_unique<CompilerInvocation>(CI)),
// External values that outlive ClangdServer
TFS(&TFS),
// Index outlives TUScheduler (declared first)
FIndex(FIndex),
// shared_ptr extends lifetime
Stdlib(Stdlib)]() mutable {
IndexFileIn IF;
IF.Symbols = indexStandardLibrary(std::move(CI), Loc, TFS);
if (Stdlib.isBest(LO))
IF.Symbols = indexStandardLibrary(std::move(CI), Loc, *TFS);
if (Stdlib->isBest(LO))
FIndex->updatePreamble(std::move(IF));
};
if (Tasks)
Expand Down Expand Up @@ -128,7 +137,7 @@ struct UpdateIndexCallbacks : public ParsingCallbacks {
FileIndex *FIndex;
ClangdServer::Callbacks *ServerCallbacks;
const ThreadsafeFS &TFS;
StdLibSet Stdlib;
std::shared_ptr<StdLibSet> Stdlib;
AsyncTaskRunner *Tasks;
};

Expand Down Expand Up @@ -233,9 +242,6 @@ ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB,
}

ClangdServer::~ClangdServer() {
// Wait for stdlib indexing to finish.
if (IndexTasks)
IndexTasks->wait();
// Destroying TUScheduler first shuts down request threads that might
// otherwise access members concurrently.
// (Nobody can be using TUScheduler because we're on the main thread).
Expand Down