Skip to content

[CAS] Delay CAS initialization on server side after daemon starts #10978

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
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
13 changes: 13 additions & 0 deletions clang/test/CAS/daemon-cas-recovery.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// REQUIRES: system-darwin, clang-cc1daemon

// RUN: rm -rf %t && mkdir -p %t

/// Construct a malformed CAS to recovery from.
// RUN: echo "abc" | llvm-cas --cas %t/cas --make-blob --data -
// RUN: rm %t/cas/v1.1/v9.data
// RUN: not llvm-cas --cas %t/cas --validate --check-hash

// RUN: env LLVM_CACHE_CAS_PATH=%t/cas LLVM_CAS_FORCE_VALIDATION=1 %clang-cache \
// RUN: %clang -fsyntax-only -x c %s

int func(void);
6 changes: 3 additions & 3 deletions clang/test/CAS/depscan-cas-log.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
// CHECK: [[PID1:[0-9]*]] {{[0-9]*}}: mmap '{{.*}}v9.index'
// CHECK: [[PID1]] {{[0-9]*}}: create subtrie

// CHECK: [[PID2:[0-9]*]] {{[0-9]*}}: mmap '{{.*}}v9.index'
// Even a minimal compilation involves at least 9 records for the cache key.
// CHECK-COUNT-9: [[PID2]] {{[0-9]*}}: create record
// CHECK-COUNT-9: [[PID1]] {{[0-9]*}}: create record

// CHECK: [[PID1]] {{[0-9]*}}: close mmap '{{.*}}v9.index'
// CHECK: [[PID2:[0-9]*]] {{[0-9]*}}: mmap '{{.*}}v9.index'
// CHECK: [[PID2]] {{[0-9]*}}: close mmap '{{.*}}v9.index'
129 changes: 68 additions & 61 deletions clang/tools/driver/cc1depscan_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,13 +355,14 @@ makeDepscanDaemonPath(StringRef Mode, const DepscanSharing &Sharing) {
return std::nullopt;
}

static Expected<llvm::cas::CASID> scanAndUpdateCC1Inline(
const char *Exec, ArrayRef<const char *> InputArgs,
StringRef WorkingDirectory, SmallVectorImpl<const char *> &OutputArgs,
bool ProduceIncludeTree, bool &DiagnosticErrorOccurred,
llvm::function_ref<const char *(const Twine &)> SaveArg,
const CASOptions &CASOpts, std::shared_ptr<llvm::cas::ObjectStore> DB,
std::shared_ptr<llvm::cas::ActionCache> Cache);
static int
scanAndUpdateCC1Inline(const char *Exec, ArrayRef<const char *> InputArgs,
StringRef WorkingDirectory,
SmallVectorImpl<const char *> &OutputArgs,
bool ProduceIncludeTree,
llvm::function_ref<const char *(const Twine &)> SaveArg,
const CASOptions &CASOpts, DiagnosticsEngine &Diag,
std::optional<llvm::cas::CASID> &RootID);

static Expected<llvm::cas::CASID> scanAndUpdateCC1InlineWithTool(
tooling::dependencies::DependencyScanningTool &Tool,
Expand All @@ -370,14 +371,17 @@ static Expected<llvm::cas::CASID> scanAndUpdateCC1InlineWithTool(
SmallVectorImpl<const char *> &OutputArgs, llvm::cas::ObjectStore &DB,
llvm::function_ref<const char *(const Twine &)> SaveArg);

static llvm::Expected<llvm::cas::CASID> scanAndUpdateCC1UsingDaemon(
static int scanAndUpdateCC1UsingDaemon(
const char *Exec, ArrayRef<const char *> OldArgs,
StringRef WorkingDirectory, SmallVectorImpl<const char *> &NewArgs,
std::string &DiagnosticOutput, StringRef Path,
const DepscanSharing &Sharing,
StringRef Path, const DepscanSharing &Sharing, DiagnosticsEngine &Diag,
llvm::function_ref<const char *(const Twine &)> SaveArg,
llvm::cas::ObjectStore &CAS) {
const CASOptions &CASOpts, std::optional<llvm::cas::CASID> &Root) {
using namespace clang::cc1depscand;
auto reportScanFailure = [&](Error E) {
Diag.Report(diag::err_cas_depscan_failed) << std::move(E);
return 1;
};

// FIXME: Skip some of this if -fcas-fs has been passed.

Expand All @@ -387,12 +391,12 @@ static llvm::Expected<llvm::cas::CASID> scanAndUpdateCC1UsingDaemon(
? ScanDaemon::connectToDaemonAndShakeHands(Path)
: ScanDaemon::constructAndShakeHands(Path, Exec, Sharing);
if (!Daemon)
return Daemon.takeError();
return reportScanFailure(Daemon.takeError());
CC1DepScanDProtocol Comms(*Daemon);

// llvm::dbgs() << "sending request...\n";
if (auto E = Comms.putCommand(WorkingDirectory, OldArgs))
return std::move(E);
return reportScanFailure(std::move(E));

llvm::BumpPtrAllocator Alloc;
llvm::StringSaver Saver(Alloc);
Expand All @@ -401,23 +405,32 @@ static llvm::Expected<llvm::cas::CASID> scanAndUpdateCC1UsingDaemon(
StringRef FailedReason;
StringRef RootID;
StringRef DiagOut;
if (auto E = Comms.getScanResult(Saver, Result, FailedReason, RootID,
RawNewArgs, DiagOut)) {
DiagnosticOutput = DiagOut;
return std::move(E);
}
DiagnosticOutput = DiagOut;
auto E = Comms.getScanResult(Saver, Result, FailedReason, RootID, RawNewArgs,
DiagOut);
// Send the diagnostics to std::err.
llvm::errs() << DiagOut;
if (E)
return reportScanFailure(std::move(E));

if (Result != CC1DepScanDProtocol::SuccessResult)
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"depscan daemon failed: " + FailedReason);
return reportScanFailure(
llvm::createStringError("depscan daemon failed: " + FailedReason));

// FIXME: Avoid this duplication.
NewArgs.resize(RawNewArgs.size());
for (int I = 0, E = RawNewArgs.size(); I != E; ++I)
NewArgs[I] = SaveArg(RawNewArgs[I]);

return CAS.parseID(RootID);
// Create CAS after daemon returns the result so daemon can perform corrupted
// CAS recovery.
auto [CAS, _] = CASOpts.getOrCreateDatabases(Diag);
if (!CAS)
return 1;

if (auto E = CAS->parseID(RootID).moveInto(Root))
return reportScanFailure(std::move(E));

return 0;
}

// FIXME: This is a copy of Command::writeResponseFile. Command is too deeply
Expand All @@ -444,8 +457,6 @@ static int scanAndUpdateCC1(const char *Exec, ArrayRef<const char *> OldArgs,
DiagnosticsEngine &Diag,
const llvm::opt::ArgList &Args,
const CASOptions &CASOpts,
std::shared_ptr<llvm::cas::ObjectStore> DB,
std::shared_ptr<llvm::cas::ActionCache> Cache,
std::optional<llvm::cas::CASID> &RootID) {
using namespace clang::driver;

Expand Down Expand Up @@ -511,25 +522,14 @@ static int scanAndUpdateCC1(const char *Exec, ArrayRef<const char *> OldArgs,
if (ProduceIncludeTree)
Sharing.CASArgs.push_back("-fdepscan-include-tree");

std::string DiagnosticOutput;
bool DiagnosticErrorOccurred = false;
auto ScanAndUpdate = [&]() {
if (std::optional<std::string> DaemonPath =
makeDepscanDaemonPath(Mode, Sharing))
return scanAndUpdateCC1UsingDaemon(Exec, OldArgs, WorkingDirectory,
NewArgs, DiagnosticOutput, *DaemonPath,
Sharing, SaveArg, *DB);
return scanAndUpdateCC1Inline(Exec, OldArgs, WorkingDirectory, NewArgs,
ProduceIncludeTree, DiagnosticErrorOccurred,
SaveArg, CASOpts, DB, Cache);
};
if (llvm::Error E = ScanAndUpdate().moveInto(RootID)) {
Diag.Report(diag::err_cas_depscan_failed) << std::move(E);
if (!DiagnosticOutput.empty())
llvm::errs() << DiagnosticOutput;
return 1;
}
return DiagnosticErrorOccurred;
if (auto DaemonPath = makeDepscanDaemonPath(Mode, Sharing))
return scanAndUpdateCC1UsingDaemon(Exec, OldArgs, WorkingDirectory, NewArgs,
*DaemonPath, Sharing, Diag, SaveArg,
CASOpts, RootID);

return scanAndUpdateCC1Inline(Exec, OldArgs, WorkingDirectory, NewArgs,
ProduceIncludeTree, SaveArg, CASOpts, Diag,
RootID);
}

int cc1depscan_main(ArrayRef<const char *> Argv, const char *Argv0,
Expand Down Expand Up @@ -590,12 +590,8 @@ int cc1depscan_main(ArrayRef<const char *> Argv, const char *Argv0,
CompilerInvocation::ParseCASArgs(CASOpts, ParsedCC1Args, Diags);
CASOpts.ensurePersistentCAS();

auto [CAS, Cache] = CASOpts.getOrCreateDatabases(Diags);
if (!CAS || !Cache)
return 1;

if (int Ret = scanAndUpdateCC1(Argv0, CC1Args->getValues(), NewArgs, Diags,
Args, CASOpts, CAS, Cache, RootID))
Args, CASOpts, RootID))
return Ret;

// FIXME: Use OutputBackend to OnDisk only now.
Expand Down Expand Up @@ -841,7 +837,8 @@ void ScanServer::start(bool Exclusive, ArrayRef<const char *> CASArgs) {
ExitOnErr(llvm::cas::validateOnDiskUnifiedCASDatabasesIfNeeded(
CASPath, /*CheckHash=*/true,
/*AllowRecovery=*/true,
/*Force=*/false, findLLVMCasBinary(Argv0, LLVMCasStorage)));
/*Force=*/getenv("LLVM_CAS_FORCE_VALIDATION"),
findLLVMCasBinary(Argv0, LLVMCasStorage)));
});

// Check the pidfile.
Expand Down Expand Up @@ -1108,13 +1105,18 @@ static Expected<llvm::cas::CASID> scanAndUpdateCC1InlineWithTool(
return *Root;
}

static Expected<llvm::cas::CASID> scanAndUpdateCC1Inline(
const char *Exec, ArrayRef<const char *> InputArgs,
StringRef WorkingDirectory, SmallVectorImpl<const char *> &OutputArgs,
bool ProduceIncludeTree, bool &DiagnosticErrorOccurred,
llvm::function_ref<const char *(const Twine &)> SaveArg,
const CASOptions &CASOpts, std::shared_ptr<llvm::cas::ObjectStore> DB,
std::shared_ptr<llvm::cas::ActionCache> Cache) {
static int
scanAndUpdateCC1Inline(const char *Exec, ArrayRef<const char *> InputArgs,
StringRef WorkingDirectory,
SmallVectorImpl<const char *> &OutputArgs,
bool ProduceIncludeTree,
llvm::function_ref<const char *(const Twine &)> SaveArg,
const CASOptions &CASOpts, DiagnosticsEngine &Diag,
std::optional<llvm::cas::CASID> &RootID) {
auto [DB, Cache] = CASOpts.getOrCreateDatabases(Diag);
if (!DB || !Cache)
return 1;

IntrusiveRefCntPtr<llvm::cas::CachingOnDiskFileSystem> FS;
if (!ProduceIncludeTree)
FS = llvm::cantFail(llvm::cas::createCachingOnDiskFileSystem(*DB));
Expand All @@ -1138,10 +1140,15 @@ static Expected<llvm::cas::CASID> scanAndUpdateCC1Inline(
auto DiagsConsumer =
std::make_unique<TextDiagnosticPrinter>(llvm::errs(), *DiagOpts, false);

auto Result = scanAndUpdateCC1InlineWithTool(
Tool, *DiagsConsumer, /*VerboseOS*/ nullptr, Exec, InputArgs,
WorkingDirectory, OutputArgs, *DB, SaveArg);
DiagnosticErrorOccurred = DiagsConsumer->getNumErrors() != 0;
return Result;
auto E = scanAndUpdateCC1InlineWithTool(
Tool, *DiagsConsumer, /*VerboseOS*/ nullptr, Exec, InputArgs,
WorkingDirectory, OutputArgs, *DB, SaveArg)
.moveInto(RootID);
if (E) {
Diag.Report(diag::err_cas_depscan_failed) << std::move(E);
return 1;
}

return DiagsConsumer->getNumErrors() != 0;
}
#endif /* LLVM_ON_UNIX */