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