Index: lld/ELF/LTO.cpp =================================================================== --- lld/ELF/LTO.cpp +++ lld/ELF/LTO.cpp @@ -175,9 +175,8 @@ if (!Config->ThinLTOCacheDir.empty()) Cache = check( lto::localCache(Config->ThinLTOCacheDir, - [&](size_t Task, std::unique_ptr MB) { - Files[Task] = std::move(MB); - })); + [&](size_t Task, std::unique_ptr MB, + StringRef Path) { Files[Task] = std::move(MB); })); checkError(LTOObj->run( [&](size_t Task) { Index: llvm/include/llvm/LTO/Caching.h =================================================================== --- llvm/include/llvm/LTO/Caching.h +++ llvm/include/llvm/LTO/Caching.h @@ -24,12 +24,13 @@ /// This type defines the callback to add a pre-existing native object file /// (e.g. in a cache). /// -/// MB->getBufferIdentifier() is a valid path for the file at the time that it -/// was opened, but clients should prefer to access MB directly in order to -/// avoid a potential race condition. +/// Path is a valid path for the file at the time that it was opened, but +/// clients should prefer to access MB directly in order to avoid a potential +/// race condition. /// /// Buffer callbacks must be thread safe. -typedef std::function MB)> +typedef std::function MB, + StringRef Path)> AddBufferFn; /// Create a local file system cache which uses the given cache directory and Index: llvm/lib/LTO/Caching.cpp =================================================================== --- llvm/lib/LTO/Caching.cpp +++ llvm/lib/LTO/Caching.cpp @@ -36,7 +36,7 @@ ErrorOr> MBOrErr = MemoryBuffer::getFile(EntryPath); if (MBOrErr) { - AddBuffer(Task, std::move(*MBOrErr)); + AddBuffer(Task, std::move(*MBOrErr), EntryPath); return AddStreamFn(); } @@ -60,22 +60,35 @@ EntryPath(std::move(EntryPath)), Task(Task) {} ~CacheStream() { - // FIXME: This code could race with the cache pruner, but it is unlikely - // that the cache pruner will choose to remove a newly created file. - // Make sure the file is closed before committing it. OS.reset(); - // This is atomic on POSIX systems. + +#ifdef _WIN32 + // Rename the file first on Windows because we cannot rename an open + // file on that platform. + // FIXME: This code could race with the cache pruner, but it is unlikely + // that the cache pruner will choose to remove a newly created file. if (auto EC = sys::fs::rename(TempFilename, EntryPath)) report_fatal_error(Twine("Failed to rename temporary file ") + TempFilename + ": " + EC.message() + "\n"); ErrorOr> MBOrErr = MemoryBuffer::getFile(EntryPath); +#else + // Open the file first to avoid racing with a cache pruner. + ErrorOr> MBOrErr = + MemoryBuffer::getFile(TempFilename); + + // This is atomic on POSIX systems. + if (auto EC = sys::fs::rename(TempFilename, EntryPath)) + report_fatal_error(Twine("Failed to rename temporary file ") + + TempFilename + ": " + EC.message() + "\n"); +#endif + if (!MBOrErr) report_fatal_error(Twine("Failed to open cache file ") + EntryPath + ": " + MBOrErr.getError().message() + "\n"); - AddBuffer(Task, std::move(*MBOrErr)); + AddBuffer(Task, std::move(*MBOrErr), EntryPath); } }; Index: llvm/tools/gold/gold-plugin.cpp =================================================================== --- llvm/tools/gold/gold-plugin.cpp +++ llvm/tools/gold/gold-plugin.cpp @@ -908,10 +908,11 @@ llvm::make_unique(FD, true)); }; - auto AddBuffer = [&](size_t Task, std::unique_ptr MB) { + auto AddBuffer = [&](size_t Task, std::unique_ptr MB, + StringRef Path) { // Note that this requires that the memory buffers provided to AddBuffer are // backed by a file. - Filenames[Task] = MB->getBufferIdentifier(); + Filenames[Task] = Path; }; NativeObjectCache Cache; Index: llvm/tools/llvm-lto2/llvm-lto2.cpp =================================================================== --- llvm/tools/llvm-lto2/llvm-lto2.cpp +++ llvm/tools/llvm-lto2/llvm-lto2.cpp @@ -296,7 +296,8 @@ return llvm::make_unique(std::move(S)); }; - auto AddBuffer = [&](size_t Task, std::unique_ptr MB) { + auto AddBuffer = [&](size_t Task, std::unique_ptr MB, + StringRef Path) { *AddStream(Task)->OS << MB->getBuffer(); };