19
19
#include " lldb/API/SBStringList.h"
20
20
#include " lldb/API/SBStructuredData.h"
21
21
#include " lldb/Host/Config.h"
22
-
22
+ #include " lldb/Host/MainLoop.h"
23
+ #include " lldb/Host/MainLoopBase.h"
24
+ #include " lldb/Utility/Status.h"
23
25
#include " llvm/ADT/StringRef.h"
24
26
#include " llvm/Support/Format.h"
25
27
#include " llvm/Support/InitLLVM.h"
50
52
51
53
using namespace lldb ;
52
54
using namespace llvm ;
55
+ using lldb_private::MainLoop;
56
+ using lldb_private::MainLoopBase;
57
+ using lldb_private::Status;
53
58
54
59
namespace {
55
60
using namespace llvm ::opt;
@@ -636,15 +641,12 @@ void Driver::UpdateWindowSize() {
636
641
}
637
642
}
638
643
639
- void sigwinch_handler (int signo) {
640
- if (g_driver != nullptr )
641
- g_driver->UpdateWindowSize ();
642
- }
643
-
644
644
void 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.
646
647
signal (SIGINT, sigint_handler);
647
648
#endif
649
+
648
650
static std::atomic_flag g_interrupt_sent = ATOMIC_FLAG_INIT;
649
651
if (g_driver != nullptr ) {
650
652
if (!g_interrupt_sent.test_and_set ()) {
@@ -657,31 +659,6 @@ void sigint_handler(int signo) {
657
659
_exit (signo);
658
660
}
659
661
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
-
685
662
static void printHelp (LLDBOptTable &table, llvm::StringRef tool_name) {
686
663
std::string usage_str = tool_name.str () + " [options]" ;
687
664
table.printHelp (llvm::outs (), usage_str.c_str (), " LLDB" , false );
@@ -787,11 +764,53 @@ int main(int argc, char const *argv[]) {
787
764
// Setup LLDB signal handlers once the debugger has been initialized.
788
765
SBDebugger::PrintDiagnosticsOnError ();
789
766
767
+ // FIXME: Migrate the SIGINT handler to be handled by the signal loop below.
790
768
signal (SIGINT, sigint_handler);
791
769
#if !defined(_WIN32)
792
770
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 (); });
795
814
#endif
796
815
797
816
int exit_code = 0 ;
@@ -824,5 +843,11 @@ int main(int argc, char const *argv[]) {
824
843
future.wait ();
825
844
}
826
845
846
+ #if !defined(_WIN32)
847
+ signal_loop.AddPendingCallback (
848
+ [](MainLoopBase &loop) { loop.RequestTermination (); });
849
+ signal_thread.join ();
850
+ #endif
851
+
827
852
return exit_code;
828
853
}
0 commit comments