diff options
Diffstat (limited to 'ELF/Filesystem.cpp')
-rw-r--r-- | ELF/Filesystem.cpp | 45 |
1 files changed, 27 insertions, 18 deletions
diff --git a/ELF/Filesystem.cpp b/ELF/Filesystem.cpp index d468ae0c618a..8d0b5d8a2f1c 100644 --- a/ELF/Filesystem.cpp +++ b/ELF/Filesystem.cpp @@ -13,8 +13,13 @@ #include "Filesystem.h" #include "Config.h" -#include "llvm/Support/FileSystem.h" +#include "lld/Common/Threads.h" +#include "llvm/Config/llvm-config.h" #include "llvm/Support/FileOutputBuffer.h" +#include "llvm/Support/FileSystem.h" +#if LLVM_ON_UNIX +#include <unistd.h> +#endif #include <thread> using namespace llvm; @@ -35,27 +40,29 @@ using namespace lld::elf; // Since LLD can link a 1 GB binary in about 5 seconds, that waste // actually counts. // -// This function spawns a background thread to call unlink. +// This function spawns a background thread to remove the file. // The calling thread returns almost immediately. void elf::unlinkAsync(StringRef Path) { - if (!Config->Threads || !sys::fs::exists(Config->OutputFile) || - !sys::fs::is_regular_file(Config->OutputFile)) +// Removing a file is async on windows. +#if defined(LLVM_ON_WIN32) + sys::fs::remove(Path); +#else + if (!ThreadsEnabled || !sys::fs::exists(Path) || + !sys::fs::is_regular_file(Path)) return; - // First, rename Path to avoid race condition. We cannot remove - // Path from a different thread because we are now going to create - // Path as a new file. If we do that in a different thread, the new - // thread can remove the new file. - SmallString<128> TempPath; - if (sys::fs::createUniqueFile(Path + "tmp%%%%%%%%", TempPath)) - return; - if (sys::fs::rename(Path, TempPath)) { - sys::fs::remove(TempPath); - return; - } + // We cannot just remove path from a different thread because we are now going + // to create path as a new file. + // Instead we open the file and unlink it on this thread. The unlink is fast + // since the open fd guarantees that it is not removing the last reference. + int FD; + std::error_code EC = sys::fs::openFileForRead(Path, FD); + sys::fs::remove(Path); - // Remove TempPath in background. - std::thread([=] { ::remove(TempPath.str().str().c_str()); }).detach(); + // close and therefore remove TempPath in background. + if (!EC) + std::thread([=] { ::close(FD); }).detach(); +#endif } // Simulate file creation to see if Path is writable. @@ -73,5 +80,7 @@ void elf::unlinkAsync(StringRef Path) { std::error_code elf::tryCreateFile(StringRef Path) { if (Path.empty()) return std::error_code(); - return FileOutputBuffer::create(Path, 1).getError(); + if (Path == "-") + return std::error_code(); + return errorToErrorCode(FileOutputBuffer::create(Path, 1).takeError()); } |