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"
24+ #include " lldb/Utility/Status.h"
2325#include " llvm/ADT/StringRef.h"
2426#include " llvm/Support/Format.h"
2527#include " llvm/Support/InitLLVM.h"
5052
5153using namespace lldb ;
5254using namespace llvm ;
55+ using lldb_private::MainLoop;
56+ using lldb_private::MainLoopBase;
57+ using lldb_private::Status;
5358
5459namespace {
5560using namespace llvm ::opt;
@@ -636,15 +641,12 @@ void Driver::UpdateWindowSize() {
636641 }
637642}
638643
639- void sigwinch_handler (int signo) {
640- if (g_driver != nullptr )
641- g_driver->UpdateWindowSize ();
642- }
643-
644644void sigint_handler (int signo) {
645- #ifdef _WIN32 // Restore handler as it is not persistent on Windows
645+ #ifdef _WIN32
646+ // Restore handler as it is not persistent on Windows.
646647 signal (SIGINT, sigint_handler);
647648#endif
649+
648650 static std::atomic_flag g_interrupt_sent = ATOMIC_FLAG_INIT;
649651 if (g_driver != nullptr ) {
650652 if (!g_interrupt_sent.test_and_set ()) {
@@ -657,31 +659,6 @@ void sigint_handler(int signo) {
657659 _exit (signo);
658660}
659661
660- #ifndef _WIN32
661- 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 ();
682- }
683- #endif
684-
685662static void printHelp (LLDBOptTable &table, llvm::StringRef tool_name) {
686663 std::string usage_str = tool_name.str () + " [options]" ;
687664 table.printHelp (llvm::outs (), usage_str.c_str (), " LLDB" , false );
@@ -787,11 +764,53 @@ int main(int argc, char const *argv[]) {
787764 // Setup LLDB signal handlers once the debugger has been initialized.
788765 SBDebugger::PrintDiagnosticsOnError ();
789766
767+ // FIXME: Migrate the SIGINT handler to be handled by the signal loop below.
790768 signal (SIGINT, sigint_handler);
791769#if !defined(_WIN32)
792770 signal (SIGPIPE, SIG_IGN);
793- signal (SIGWINCH, sigwinch_handler);
794- signal (SIGTSTP, sigtstp_handler);
771+
772+ // Handle signals in a MainLoop running on a separate thread.
773+ MainLoop signal_loop;
774+ Status signal_status;
775+
776+ auto sigwinch_handler = signal_loop.RegisterSignal (
777+ SIGWINCH,
778+ [&](MainLoopBase &) {
779+ if (g_driver)
780+ g_driver->UpdateWindowSize ();
781+ },
782+ signal_status);
783+ assert (sigwinch_handler && signal_status.Success ());
784+
785+ auto sigtstp_handler = signal_loop.RegisterSignal (
786+ SIGTSTP,
787+ [&](MainLoopBase &) {
788+ if (g_driver)
789+ g_driver->GetDebugger ().SaveInputTerminalState ();
790+
791+ struct sigaction old_action;
792+ struct sigaction new_action = {};
793+ new_action.sa_handler = SIG_DFL;
794+ sigemptyset (&new_action.sa_mask );
795+ sigaddset (&new_action.sa_mask , SIGTSTP);
796+
797+ int ret = sigaction (SIGTSTP, &new_action, &old_action);
798+ UNUSED_IF_ASSERT_DISABLED (ret);
799+ assert (ret == 0 && " sigaction failed" );
800+
801+ raise (SIGTSTP);
802+
803+ ret = sigaction (SIGTSTP, &old_action, nullptr );
804+ UNUSED_IF_ASSERT_DISABLED (ret);
805+ assert (ret == 0 && " sigaction failed" );
806+
807+ if (g_driver)
808+ g_driver->GetDebugger ().RestoreInputTerminalState ();
809+ },
810+ signal_status);
811+ assert (sigtstp_handler && signal_status.Success ());
812+
813+ std::thread signal_thread ([&] { signal_loop.Run (); });
795814#endif
796815
797816 int exit_code = 0 ;
@@ -824,5 +843,11 @@ int main(int argc, char const *argv[]) {
824843 future.wait ();
825844 }
826845
846+ #if !defined(_WIN32)
847+ signal_loop.AddPendingCallback (
848+ [](MainLoopBase &loop) { loop.RequestTermination (); });
849+ signal_thread.join ();
850+ #endif
851+
827852 return exit_code;
828853}
0 commit comments