diff options
author | Pavel Labath <labath@google.com> | 2017-10-23 19:41:17 +0000 |
---|---|---|
committer | Pavel Labath <labath@google.com> | 2017-10-23 19:41:17 +0000 |
commit | d813309e034cb32436eb804f70d94da7bdb406cd (patch) | |
tree | a226dcb93a66651509b88713fec41f153a1ba653 /lldb/source/Utility/Log.cpp | |
parent | 6f06b6edff4eb63703875e2785c18eea5d83e55c (diff) | |
download | bcm5719-llvm-d813309e034cb32436eb804f70d94da7bdb406cd.tar.gz bcm5719-llvm-d813309e034cb32436eb804f70d94da7bdb406cd.zip |
Logging: Disable logging after fork()
Summary:
We had a bug where if we had forked (in the ProcessLauncherPosixFork)
while another thread was writing a log message, we would deadlock. This
happened because the fork child inherited the locked log rwmutex, which
would never get unlocked. This meant the child got stuck trying to
disable all log channels.
The bug existed for a while but only started being apparent after
D37930, which started using ThreadLauncher (which uses logging) instead
of std::thread (which does not) for launching TaskPool threads.
The fix is to use pthread_atfork to disable logging in the forked child.
Reviewers: zturner, eugene, clayborg
Subscribers: lldb-commits
Differential Revision: https://reviews.llvm.org/D38938
llvm-svn: 316368
Diffstat (limited to 'lldb/source/Utility/Log.cpp')
-rw-r--r-- | lldb/source/Utility/Log.cpp | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/lldb/source/Utility/Log.cpp b/lldb/source/Utility/Log.cpp index a80b106838b..78050dbea68 100644 --- a/lldb/source/Utility/Log.cpp +++ b/lldb/source/Utility/Log.cpp @@ -32,6 +32,7 @@ #include <process.h> // for getpid #else #include <unistd.h> +#include <pthread.h> #endif using namespace lldb_private; @@ -181,6 +182,13 @@ void Log::Warning(const char *format, ...) { Printf("warning: %s", Content.c_str()); } +void Log::Initialize() { +#ifdef LLVM_ON_UNIX + pthread_atfork(nullptr, nullptr, &Log::DisableLoggingChild); +#endif + InitializeLldbChannel(); +} + void Log::Register(llvm::StringRef name, Channel &channel) { auto iter = g_channel_map->try_emplace(name, channel); assert(iter.second == true); @@ -321,3 +329,11 @@ void Log::Format(llvm::StringRef file, llvm::StringRef function, message << payload << "\n"; WriteMessage(message.str()); } + +void Log::DisableLoggingChild() { + // Disable logging by clearing out the atomic variable after forking -- if we + // forked while another thread held the channel mutex, we would deadlock when + // trying to write to the log. + for (auto &c: *g_channel_map) + c.second.m_channel.log_ptr.store(nullptr, std::memory_order_relaxed); +} |