1c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham"""
2c4392dc344eb0c850dae74948bf249691ad9eb41Jim InghamTest calling a function that hits a signal set to auto-restart, make sure the call completes.
3c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham"""
4c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
5c4392dc344eb0c850dae74948bf249691ad9eb41Jim Inghamimport unittest2
6c4392dc344eb0c850dae74948bf249691ad9eb41Jim Inghamimport lldb
7c4392dc344eb0c850dae74948bf249691ad9eb41Jim Inghamimport lldbutil
8c4392dc344eb0c850dae74948bf249691ad9eb41Jim Inghamfrom lldbtest import *
9c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
10c4392dc344eb0c850dae74948bf249691ad9eb41Jim Inghamclass ExprCommandWithTimeoutsTestCase(TestBase):
11c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
12c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham    mydir = os.path.join("expression_command", "call-restarts")
13c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
14c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham    def setUp(self):
15c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        # Call super's setUp().
16c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        TestBase.setUp(self)
17c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
18c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.main_source = "lotta-signals.c"
19c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.main_source_spec = lldb.SBFileSpec (self.main_source)
20c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
21c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
22c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
23c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham    @dsym_test
24c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham    def test_with_dsym(self):
25c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        """Test calling std::String member function."""
26c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.buildDsym()
27c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.call_function()
28c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
296bc4dcdfbcdfa455299d2123011b82a77351ee72Daniel Malea    @skipIfLinux # llvm.org/pr15278: handle expressions that generate signals on Linux
30c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham    @dwarf_test
31c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham    def test_with_dwarf(self):
32c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        """Test calling std::String member function."""
33c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.buildDwarf()
34c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.call_function()
35c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
36c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham    def check_after_call (self, num_sigchld):
37c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        after_call = self.sigchld_no.GetValueAsSigned(-1)
38c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue (after_call - self.start_sigchld_no == num_sigchld, "Really got %d SIGCHLD signals through the call."%(num_sigchld))
39c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.start_sigchld_no = after_call
40c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
41c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        # Check that we are back where we were before:
42c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        frame = self.thread.GetFrameAtIndex(0)
43c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue (self.orig_frame_pc == frame.GetPC(), "Restored the zeroth frame correctly")
44c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
45c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
46c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham    def call_function(self):
47c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        """Test calling function with timeout."""
48c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        exe_name = "a.out"
49c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        exe = os.path.join(os.getcwd(), exe_name)
50c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
51c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        target = self.dbg.CreateTarget(exe)
52c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue(target, VALID_TARGET)
53c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        empty = lldb.SBFileSpec()
54c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        breakpoint = target.BreakpointCreateBySourceRegex('Stop here in main.',self.main_source_spec)
55c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue(breakpoint.GetNumLocations() > 0, VALID_BREAKPOINT)
56c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
57c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        # Launch the process, and do not stop at the entry point.
58c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        process = target.LaunchSimple(None, None, os.getcwd())
59c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
60c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue(process, PROCESS_IS_VALID)
61c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
62c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        # Frame #0 should be at our breakpoint.
63c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        threads = lldbutil.get_threads_stopped_at_breakpoint (process, breakpoint)
64c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
65c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue(len(threads) == 1)
66c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.thread = threads[0]
67c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
68c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        # Make sure the SIGCHLD behavior is pass/no-stop/no-notify:
69c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        return_obj = lldb.SBCommandReturnObject()
70c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.dbg.GetCommandInterpreter().HandleCommand("process handle SIGCHLD -s 0 -p 1 -n 0", return_obj)
71c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue (return_obj.Succeeded() == True, "Set SIGCHLD to pass, no-stop")
72c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
73c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        # The sigchld_no variable should be 0 at this point.
74c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.sigchld_no = target.FindFirstGlobalVariable("sigchld_no")
75c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue (self.sigchld_no.IsValid(), "Got a value for sigchld_no")
76c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
77c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.start_sigchld_no = self.sigchld_no.GetValueAsSigned (-1)
78c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue (self.start_sigchld_no != -1, "Got an actual value for sigchld_no")
79c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
80c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        options = lldb.SBExpressionOptions()
81c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        options.SetUnwindOnError(True)
82c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
83c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        frame = self.thread.GetFrameAtIndex(0)
84c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        # Store away the PC to check that the functions unwind to the right place after calls
85c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.orig_frame_pc = frame.GetPC()
86c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
87c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        num_sigchld = 30
88c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        value = frame.EvaluateExpression ("call_me (%d)"%(num_sigchld), options)
89c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue (value.IsValid())
90c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue (value.GetError().Success() == True)
91c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue (value.GetValueAsSigned(-1) == num_sigchld)
92c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
93c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.check_after_call(num_sigchld)
94c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
95c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        # Okay, now try with a breakpoint in the called code in the case where
96c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        # we are ignoring breakpoint hits.
97c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        handler_bkpt = target.BreakpointCreateBySourceRegex("Got sigchld %d.", self.main_source_spec)
98c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue (handler_bkpt.GetNumLocations() > 0)
99c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        options.SetIgnoreBreakpoints(True)
100c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        options.SetUnwindOnError(True)
101c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
102c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        value = frame.EvaluateExpression("call_me (%d)"%(num_sigchld), options)
103c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
104c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue (value.IsValid() and value.GetError().Success() == True)
105c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue (value.GetValueAsSigned(-1) == num_sigchld)
106c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.check_after_call(num_sigchld)
107c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
108c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        # Now set the signal to print but not stop and make sure that calling still works:
109c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.dbg.GetCommandInterpreter().HandleCommand("process handle SIGCHLD -s 0 -p 1 -n 1", return_obj)
110c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue (return_obj.Succeeded() == True, "Set SIGCHLD to pass, no-stop, notify")
111c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
112c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        value = frame.EvaluateExpression("call_me (%d)"%(num_sigchld), options)
113c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
114c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue (value.IsValid() and value.GetError().Success() == True)
115c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue (value.GetValueAsSigned(-1) == num_sigchld)
116c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.check_after_call(num_sigchld)
117c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
118c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        # Now set this unwind on error to false, and make sure that we still complete the call:
119c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        options.SetUnwindOnError(False)
120c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        value = frame.EvaluateExpression("call_me (%d)"%(num_sigchld), options)
121c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
122c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue (value.IsValid() and value.GetError().Success() == True)
123c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue (value.GetValueAsSigned(-1) == num_sigchld)
124c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.check_after_call(num_sigchld)
125c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
126c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        # Okay, now set UnwindOnError to true, and then make the signal behavior to stop
127c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        # and see that now we do stop at the signal point:
128c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
129c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.dbg.GetCommandInterpreter().HandleCommand("process handle SIGCHLD -s 1 -p 1 -n 1", return_obj)
130c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue (return_obj.Succeeded() == True, "Set SIGCHLD to pass, stop, notify")
131c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
132c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        value = frame.EvaluateExpression("call_me (%d)"%(num_sigchld), options)
133c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue (value.IsValid() and value.GetError().Success() == False)
134c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
135c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        # Set signal handling back to no-stop, and continue and we should end up back in out starting frame:
136c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.dbg.GetCommandInterpreter().HandleCommand("process handle SIGCHLD -s 0 -p 1 -n 1", return_obj)
137c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue (return_obj.Succeeded() == True, "Set SIGCHLD to pass, no-stop, notify")
138c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
139c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        error = process.Continue()
140c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue (error.Success(), "Continuing after stopping for signal succeeds.")
141c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
142c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        frame = self.thread.GetFrameAtIndex(0)
143c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham        self.assertTrue (frame.GetPC() == self.orig_frame_pc, "Continuing returned to the place we started.")
144c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham
145c4392dc344eb0c850dae74948bf249691ad9eb41Jim Inghamif __name__ == '__main__':
146c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham    import atexit
147c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham    lldb.SBDebugger.Initialize()
148c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham    atexit.register(lambda: lldb.SBDebugger.Terminate())
149c4392dc344eb0c850dae74948bf249691ad9eb41Jim Ingham    unittest2.main()
150