[lld] r315033 - Wait for all threads to terminate before exitting.
Rui Ueyama via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 5 16:01:12 PDT 2017
Author: ruiu
Date: Thu Oct 5 16:01:11 2017
New Revision: 315033
URL: http://llvm.org/viewvc/llvm-project?rev=315033&view=rev
Log:
Wait for all threads to terminate before exitting.
I think it is not defined what would happen to detached threads
when the main thread tries to exit. That means it was not guaranteed
that unlinkAsync correctly removes a temporary file. It was also
reported that this unlinkAsync caused a crash on Windows.
This patch adds a few new functions so that the main thread always
waits for non-main threads before exitting.
I don't actually like the new two functions, runBackground and
waitForBackgroundThreads, because it looks like it is a bit
overdesigned. After all, what we are doing with these functions
is to just remove a file.
An alternative would be to do fork(2) and make the child process
remove a file asynchronously. However, it has its own problems.
Correctly forking and reclaiming a resource using waitpid(2) is not
doable unless we know our process-wide settings (such as signal mask),
but we can't make any assumption on it when lld is embedded to other
process. So I chose to stick with threads instead of multi-processes.
Differential Revision: https://reviews.llvm.org/D38571
Added:
lld/trunk/ELF/Threads.cpp
Modified:
lld/trunk/ELF/CMakeLists.txt
lld/trunk/ELF/Driver.cpp
lld/trunk/ELF/Error.cpp
lld/trunk/ELF/Filesystem.cpp
lld/trunk/ELF/Threads.h
Modified: lld/trunk/ELF/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/CMakeLists.txt?rev=315033&r1=315032&r2=315033&view=diff
==============================================================================
--- lld/trunk/ELF/CMakeLists.txt (original)
+++ lld/trunk/ELF/CMakeLists.txt Thu Oct 5 16:01:11 2017
@@ -40,6 +40,7 @@ add_lld_library(lldELF
Symbols.cpp
SyntheticSections.cpp
Target.cpp
+ Threads.cpp
Thunks.cpp
Writer.cpp
Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=315033&r1=315032&r2=315033&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Thu Oct 5 16:01:11 2017
@@ -89,6 +89,7 @@ bool elf::link(ArrayRef<const char *> Ar
Config->Argv = {Args.begin(), Args.end()};
Driver->main(Args, CanExitEarly);
+ waitForBackgroundThreads();
// Exit immediately if we don't need to return to the caller.
// This saves time because the overhead of calling destructors
Modified: lld/trunk/ELF/Error.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Error.cpp?rev=315033&r1=315032&r2=315033&view=diff
==============================================================================
--- lld/trunk/ELF/Error.cpp (original)
+++ lld/trunk/ELF/Error.cpp Thu Oct 5 16:01:11 2017
@@ -9,6 +9,7 @@
#include "Error.h"
#include "Config.h"
+#include "Threads.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Error.h"
@@ -100,6 +101,8 @@ void elf::error(const Twine &Msg) {
}
void elf::exitLld(int Val) {
+ waitForBackgroundThreads();
+
// Dealloc/destroy ManagedStatic variables before calling
// _exit(). In a non-LTO build, this is a nop. In an LTO
// build allows us to get the output of -time-passes.
Modified: lld/trunk/ELF/Filesystem.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Filesystem.cpp?rev=315033&r1=315032&r2=315033&view=diff
==============================================================================
--- lld/trunk/ELF/Filesystem.cpp (original)
+++ lld/trunk/ELF/Filesystem.cpp Thu Oct 5 16:01:11 2017
@@ -13,9 +13,9 @@
#include "Filesystem.h"
#include "Config.h"
-#include "llvm/Support/FileSystem.h"
+#include "Threads.h"
#include "llvm/Support/FileOutputBuffer.h"
-#include <thread>
+#include "llvm/Support/FileSystem.h"
using namespace llvm;
@@ -55,7 +55,7 @@ void elf::unlinkAsync(StringRef Path) {
}
// Remove TempPath in background.
- std::thread([=] { ::remove(TempPath.str().str().c_str()); }).detach();
+ runBackground([=] { ::remove(TempPath.str().str().c_str()); });
}
// Simulate file creation to see if Path is writable.
Added: lld/trunk/ELF/Threads.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Threads.cpp?rev=315033&view=auto
==============================================================================
--- lld/trunk/ELF/Threads.cpp (added)
+++ lld/trunk/ELF/Threads.cpp Thu Oct 5 16:01:11 2017
@@ -0,0 +1,29 @@
+//===- Threads.cpp --------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Threads.h"
+#include <thread>
+
+static std::vector<std::thread> Threads;
+
+// Runs a given function in a new thread.
+void lld::elf::runBackground(std::function<void()> Fn) {
+ Threads.emplace_back(Fn);
+}
+
+// Wait for all threads spawned for runBackground() to finish.
+//
+// You need to call this function from the main thread before exiting
+// because it is not defined what will happen to non-main threads when
+// the main thread exits.
+void lld::elf::waitForBackgroundThreads() {
+ for (std::thread &T : Threads)
+ if (T.joinable())
+ T.join();
+}
Modified: lld/trunk/ELF/Threads.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Threads.h?rev=315033&r1=315032&r2=315033&view=diff
==============================================================================
--- lld/trunk/ELF/Threads.h (original)
+++ lld/trunk/ELF/Threads.h Thu Oct 5 16:01:11 2017
@@ -81,6 +81,10 @@ inline void parallelForEachN(size_t Begi
else
for_each_n(llvm::parallel::seq, Begin, End, Fn);
}
+
+void runBackground(std::function<void()> Fn);
+void waitForBackgroundThreads();
+
} // namespace elf
} // namespace lld
More information about the llvm-commits
mailing list