https://github.com/JDevlieghere updated https://github.com/llvm/llvm-project/pull/134956
>From 390942ce3a1cf6c51f95e8e2893f88807a48e745 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere <jo...@devlieghere.com> Date: Tue, 8 Apr 2025 17:33:41 -0700 Subject: [PATCH 1/2] [lldb] Handle signals in a separate thread in the driver Handle signals in a separate thread in the driver so that we can stop worrying about signal safety of functions in libLLDB that may get called from a signal handler. --- lldb/tools/driver/CMakeLists.txt | 2 + lldb/tools/driver/Driver.cpp | 96 +++++++++++++++++++++----------- 2 files changed, 64 insertions(+), 34 deletions(-) diff --git a/lldb/tools/driver/CMakeLists.txt b/lldb/tools/driver/CMakeLists.txt index 89884ecd0601b..8b4aa92f96f0d 100644 --- a/lldb/tools/driver/CMakeLists.txt +++ b/lldb/tools/driver/CMakeLists.txt @@ -22,6 +22,8 @@ add_lldb_tool(lldb LINK_LIBS liblldb + lldbHost + lldbUtility LINK_COMPONENTS Option diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp index 15cb0134fec8e..fb051f198381f 100644 --- a/lldb/tools/driver/Driver.cpp +++ b/lldb/tools/driver/Driver.cpp @@ -19,7 +19,9 @@ #include "lldb/API/SBStringList.h" #include "lldb/API/SBStructuredData.h" #include "lldb/Host/Config.h" - +#include "lldb/Host/MainLoop.h" +#include "lldb/Host/MainLoopBase.h" +#include "lldb/Utility/Status.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Format.h" #include "llvm/Support/InitLLVM.h" @@ -50,6 +52,9 @@ using namespace lldb; using namespace llvm; +using lldb_private::MainLoop; +using lldb_private::MainLoopBase; +using lldb_private::Status; namespace { using namespace llvm::opt; @@ -636,15 +641,12 @@ void Driver::UpdateWindowSize() { } } -void sigwinch_handler(int signo) { - if (g_driver != nullptr) - g_driver->UpdateWindowSize(); -} - void sigint_handler(int signo) { -#ifdef _WIN32 // Restore handler as it is not persistent on Windows +#ifdef _WIN32 + // Restore handler as it is not persistent on Windows. signal(SIGINT, sigint_handler); #endif + static std::atomic_flag g_interrupt_sent = ATOMIC_FLAG_INIT; if (g_driver != nullptr) { if (!g_interrupt_sent.test_and_set()) { @@ -657,31 +659,6 @@ void sigint_handler(int signo) { _exit(signo); } -#ifndef _WIN32 -static void sigtstp_handler(int signo) { - if (g_driver != nullptr) - g_driver->GetDebugger().SaveInputTerminalState(); - - // Unblock the signal and remove our handler. - sigset_t set; - sigemptyset(&set); - sigaddset(&set, signo); - pthread_sigmask(SIG_UNBLOCK, &set, nullptr); - signal(signo, SIG_DFL); - - // Now re-raise the signal. We will immediately suspend... - raise(signo); - // ... and resume after a SIGCONT. - - // Now undo the modifications. - pthread_sigmask(SIG_BLOCK, &set, nullptr); - signal(signo, sigtstp_handler); - - if (g_driver != nullptr) - g_driver->GetDebugger().RestoreInputTerminalState(); -} -#endif - static void printHelp(LLDBOptTable &table, llvm::StringRef tool_name) { std::string usage_str = tool_name.str() + " [options]"; table.printHelp(llvm::outs(), usage_str.c_str(), "LLDB", false); @@ -787,11 +764,56 @@ int main(int argc, char const *argv[]) { // Setup LLDB signal handlers once the debugger has been initialized. SBDebugger::PrintDiagnosticsOnError(); + // FIXME: Migrate the SIGINT handler to be handled by the signal loop below. signal(SIGINT, sigint_handler); #if !defined(_WIN32) signal(SIGPIPE, SIG_IGN); - signal(SIGWINCH, sigwinch_handler); - signal(SIGTSTP, sigtstp_handler); + + // Handle signals in a MainLoop running on a separate thread. + MainLoop signal_loop; + Status signal_status; + + auto sigwinch_handler = signal_loop.RegisterSignal( + SIGWINCH, + [&](MainLoopBase &) { + if (g_driver) + g_driver->UpdateWindowSize(); + }, + signal_status); + assert(sigwinch_handler && signal_status.Success()); + + auto sigtstp_handler = signal_loop.RegisterSignal( + SIGTSTP, + [&](MainLoopBase &) { + if (g_driver) + g_driver->GetDebugger().SaveInputTerminalState(); + + struct sigaction old_action; + struct sigaction new_action; + + memset(&new_action, 0, sizeof(new_action)); + new_action.sa_handler = SIG_DFL; + new_action.sa_flags = SA_SIGINFO; + sigemptyset(&new_action.sa_mask); + sigaddset(&new_action.sa_mask, SIGTSTP); + + int ret = sigaction(SIGTSTP, &new_action, &old_action); + UNUSED_IF_ASSERT_DISABLED(ret); + assert(ret == 0 && "sigaction failed"); + + raise(SIGTSTP); + + ret = sigaction(SIGTSTP, &old_action, nullptr); + UNUSED_IF_ASSERT_DISABLED(ret); + assert(ret == 0 && "sigaction failed"); + + if (g_driver) + g_driver->GetDebugger().RestoreInputTerminalState(); + }, + signal_status); + assert(sigtstp_handler && signal_status.Success()); + + std::thread signal_thread([&] { signal_loop.Run(); }); #endif int exit_code = 0; @@ -824,5 +846,11 @@ int main(int argc, char const *argv[]) { future.wait(); } +#if !defined(_WIN32) + signal_loop.AddPendingCallback( + [](MainLoopBase &loop) { loop.RequestTermination(); }); + signal_thread.join(); +#endif + return exit_code; } >From a2fae8be8a0f3cfc9b9bc36704c32c3f1bc640c9 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere <jo...@devlieghere.com> Date: Thu, 10 Apr 2025 08:38:20 -0700 Subject: [PATCH 2/2] Address Pavel's feedback --- lldb/tools/driver/Driver.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lldb/tools/driver/Driver.cpp b/lldb/tools/driver/Driver.cpp index fb051f198381f..e19fded051941 100644 --- a/lldb/tools/driver/Driver.cpp +++ b/lldb/tools/driver/Driver.cpp @@ -789,11 +789,8 @@ int main(int argc, char const *argv[]) { g_driver->GetDebugger().SaveInputTerminalState(); struct sigaction old_action; - struct sigaction new_action; - - memset(&new_action, 0, sizeof(new_action)); + struct sigaction new_action = {}; new_action.sa_handler = SIG_DFL; - new_action.sa_flags = SA_SIGINFO; sigemptyset(&new_action.sa_mask); sigaddset(&new_action.sa_mask, SIGTSTP); _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits