Skip to content

Commit ea8bfa0

Browse files
committed
[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.
1 parent 36cb81c commit ea8bfa0

File tree

2 files changed

+48
-31
lines changed

2 files changed

+48
-31
lines changed

lldb/tools/driver/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ add_lldb_tool(lldb
2222

2323
LINK_LIBS
2424
liblldb
25+
lldbHost
2526

2627
LINK_COMPONENTS
2728
Option

lldb/tools/driver/Driver.cpp

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
#include "lldb/API/SBStringList.h"
2020
#include "lldb/API/SBStructuredData.h"
2121
#include "lldb/Host/Config.h"
22-
22+
#include "lldb/Host/MainLoop.h"
23+
#include "lldb/Host/MainLoopBase.h"
2324
#include "llvm/ADT/StringRef.h"
2425
#include "llvm/Support/Format.h"
2526
#include "llvm/Support/InitLLVM.h"
@@ -50,6 +51,8 @@
5051

5152
using namespace lldb;
5253
using namespace llvm;
54+
using lldb_private::MainLoop;
55+
using lldb_private::MainLoopBase;
5356

5457
namespace {
5558
using namespace llvm::opt;
@@ -89,6 +92,7 @@ static struct termios g_old_stdin_termios;
8992
static bool disable_color(const raw_ostream &OS) { return false; }
9093

9194
static Driver *g_driver = nullptr;
95+
static MainLoop g_signal_loop;
9296

9397
// In the Driver::MainLoop, we change the terminal settings. This function is
9498
// added as an atexit handler to make sure we clean them up.
@@ -637,48 +641,50 @@ void Driver::UpdateWindowSize() {
637641
}
638642

639643
void sigwinch_handler(int signo) {
640-
if (g_driver != nullptr)
641-
g_driver->UpdateWindowSize();
644+
g_signal_loop.AddPendingCallback([](MainLoopBase &loop) {
645+
if (g_driver != nullptr)
646+
g_driver->UpdateWindowSize();
647+
});
642648
}
643649

644650
void sigint_handler(int signo) {
645651
#ifdef _WIN32 // Restore handler as it is not persistent on Windows
646652
signal(SIGINT, sigint_handler);
647653
#endif
648-
static std::atomic_flag g_interrupt_sent = ATOMIC_FLAG_INIT;
649-
if (g_driver != nullptr) {
650-
if (!g_interrupt_sent.test_and_set()) {
651-
g_driver->GetDebugger().DispatchInputInterrupt();
652-
g_interrupt_sent.clear();
653-
return;
654+
g_signal_loop.AddPendingCallback([signo](MainLoopBase &loop) {
655+
static std::atomic_flag g_interrupt_sent = ATOMIC_FLAG_INIT;
656+
if (g_driver != nullptr) {
657+
if (!g_interrupt_sent.test_and_set()) {
658+
g_driver->GetDebugger().DispatchInputInterrupt();
659+
g_interrupt_sent.clear();
660+
return;
661+
}
654662
}
655-
}
656663

657-
_exit(signo);
664+
loop.RequestTermination();
665+
_exit(signo);
666+
});
658667
}
659668

660669
#ifndef _WIN32
661670
static void sigtstp_handler(int signo) {
662-
if (g_driver != nullptr)
663-
g_driver->GetDebugger().SaveInputTerminalState();
664-
665-
// Unblock the signal and remove our handler.
666-
sigset_t set;
667-
sigemptyset(&set);
668-
sigaddset(&set, signo);
669-
pthread_sigmask(SIG_UNBLOCK, &set, nullptr);
670-
signal(signo, SIG_DFL);
671-
672-
// Now re-raise the signal. We will immediately suspend...
673-
raise(signo);
674-
// ... and resume after a SIGCONT.
675-
676-
// Now undo the modifications.
677-
pthread_sigmask(SIG_BLOCK, &set, nullptr);
678-
signal(signo, sigtstp_handler);
679-
680-
if (g_driver != nullptr)
681-
g_driver->GetDebugger().RestoreInputTerminalState();
671+
g_signal_loop.AddPendingCallback([signo](MainLoopBase &loop) {
672+
if (g_driver != nullptr)
673+
g_driver->GetDebugger().SaveInputTerminalState();
674+
675+
// Remove our handler.
676+
signal(signo, SIG_DFL);
677+
678+
// Now re-raise the signal. We will immediately suspend...
679+
raise(signo);
680+
// ... and resume after a SIGCONT.
681+
682+
// Now undo the modifications.
683+
signal(signo, sigtstp_handler);
684+
685+
if (g_driver != nullptr)
686+
g_driver->GetDebugger().RestoreInputTerminalState();
687+
});
682688
}
683689
#endif
684690

@@ -794,6 +800,10 @@ int main(int argc, char const *argv[]) {
794800
signal(SIGTSTP, sigtstp_handler);
795801
#endif
796802

803+
// Run the signal handling MainLoop on a separate thread.
804+
std::thread signal_thread([] { g_signal_loop.Run(); });
805+
signal_thread.detach();
806+
797807
int exit_code = 0;
798808
// Create a scope for driver so that the driver object will destroy itself
799809
// before SBDebugger::Terminate() is called.
@@ -824,5 +834,11 @@ int main(int argc, char const *argv[]) {
824834
future.wait();
825835
}
826836

837+
// Stop the signal handler thread. Do this after calling SBDebugger::Terminate
838+
// so that impatient users can send a SIGSTOP if they don't want to wait for
839+
// the background threads to exit cleanly.
840+
g_signal_loop.AddPendingCallback(
841+
[](MainLoopBase &loop) { loop.RequestTermination(); });
842+
827843
return exit_code;
828844
}

0 commit comments

Comments
 (0)