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,11 @@ 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
+ #ifdef _WIN32
644
645
void sigint_handler (int signo) {
645
- # ifdef _WIN32 // Restore handler as it is not persistent on Windows
646
+ // Restore handler as it is not persistent on Windows.
646
647
signal (SIGINT, sigint_handler);
647
- # endif
648
+
648
649
static std::atomic_flag g_interrupt_sent = ATOMIC_FLAG_INIT;
649
650
if (g_driver != nullptr ) {
650
651
if (!g_interrupt_sent.test_and_set ()) {
@@ -656,30 +657,6 @@ void sigint_handler(int signo) {
656
657
657
658
_exit (signo);
658
659
}
659
-
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
660
#endif
684
661
685
662
static void printHelp (LLDBOptTable &table, llvm::StringRef tool_name) {
@@ -787,11 +764,75 @@ 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
+ #if defined(_WIN32)
768
+ // FIXME: Support signals in MainLoopWindows and handle SIGINT in the signal
769
+ // loop below.
790
770
signal (SIGINT, sigint_handler);
791
- #if !defined(_WIN32)
771
+ #else
792
772
signal (SIGPIPE, SIG_IGN);
793
- signal (SIGWINCH, sigwinch_handler);
794
- signal (SIGTSTP, sigtstp_handler);
773
+
774
+ // Handle signals in a MainLoop running on a separate thread.
775
+ MainLoop signal_loop;
776
+ Status signal_status;
777
+
778
+ auto sigint_handler = signal_loop.RegisterSignal (
779
+ SIGINT,
780
+ [&](MainLoopBase &loop) {
781
+ static std::atomic_flag g_interrupt_sent = ATOMIC_FLAG_INIT;
782
+ if (g_driver) {
783
+ if (!g_interrupt_sent.test_and_set ()) {
784
+ g_driver->GetDebugger ().DispatchInputInterrupt ();
785
+ g_interrupt_sent.clear ();
786
+ return ;
787
+ }
788
+ }
789
+ loop.RequestTermination ();
790
+ _exit (SIGINT);
791
+ },
792
+ signal_status);
793
+ assert (sigint_handler && signal_status.Success ());
794
+
795
+ auto sigwinch_handler = signal_loop.RegisterSignal (
796
+ SIGWINCH,
797
+ [&](MainLoopBase &) {
798
+ if (g_driver)
799
+ g_driver->UpdateWindowSize ();
800
+ },
801
+ signal_status);
802
+ assert (sigwinch_handler && signal_status.Success ());
803
+
804
+ auto sigtstp_handler = signal_loop.RegisterSignal (
805
+ SIGTSTP,
806
+ [&](MainLoopBase &) {
807
+ if (g_driver)
808
+ g_driver->GetDebugger ().SaveInputTerminalState ();
809
+
810
+ struct sigaction old_action;
811
+ struct sigaction new_action;
812
+
813
+ memset (&new_action, 0 , sizeof (new_action));
814
+ new_action.sa_handler = SIG_DFL;
815
+ new_action.sa_flags = SA_SIGINFO;
816
+ sigemptyset (&new_action.sa_mask );
817
+ sigaddset (&new_action.sa_mask , SIGTSTP);
818
+
819
+ int ret = sigaction (SIGTSTP, &new_action, &old_action);
820
+ UNUSED_IF_ASSERT_DISABLED (ret);
821
+ assert (ret == 0 && " sigaction failed" );
822
+
823
+ raise (SIGTSTP);
824
+
825
+ ret = sigaction (SIGTSTP, &old_action, nullptr );
826
+ UNUSED_IF_ASSERT_DISABLED (ret);
827
+ assert (ret == 0 && " sigaction failed" );
828
+
829
+ if (g_driver)
830
+ g_driver->GetDebugger ().RestoreInputTerminalState ();
831
+ },
832
+ signal_status);
833
+ assert (sigtstp_handler && signal_status.Success ());
834
+
835
+ std::thread signal_thread ([&] { signal_loop.Run (); });
795
836
#endif
796
837
797
838
int exit_code = 0 ;
@@ -824,5 +865,11 @@ int main(int argc, char const *argv[]) {
824
865
future.wait ();
825
866
}
826
867
868
+ #if !defined(_WIN32)
869
+ signal_loop.AddPendingCallback (
870
+ [](MainLoopBase &loop) { loop.RequestTermination (); });
871
+ signal_thread.join ();
872
+ #endif
873
+
827
874
return exit_code;
828
875
}
0 commit comments