1""" 2Test calling a function that hits a signal set to auto-restart, make sure the call completes. 3""" 4 5 6 7import lldb 8from lldbsuite.test.decorators import * 9from lldbsuite.test.lldbtest import * 10from lldbsuite.test import lldbutil 11 12 13class ExprCommandThatRestartsTestCase(TestBase): 14 15 mydir = TestBase.compute_mydir(__file__) 16 NO_DEBUG_INFO_TESTCASE = True 17 18 def setUp(self): 19 # Call super's setUp(). 20 TestBase.setUp(self) 21 22 self.main_source = "lotta-signals.c" 23 self.main_source_spec = lldb.SBFileSpec(self.main_source) 24 25 @skipIfDarwin # llvm.org/pr19246: intermittent failure 26 @skipIfWindows # Test relies on signals, unsupported on Windows 27 @expectedFlakeyAndroid(bugnumber="llvm.org/pr19246") 28 @expectedFailureNetBSD 29 def test(self): 30 """Test calling function that hits a signal and restarts.""" 31 self.build() 32 self.call_function() 33 34 def check_after_call(self, num_sigchld): 35 after_call = self.sigchld_no.GetValueAsSigned(-1) 36 self.assertTrue( 37 after_call - 38 self.start_sigchld_no == num_sigchld, 39 "Really got %d SIGCHLD signals through the call." % 40 (num_sigchld)) 41 self.start_sigchld_no = after_call 42 43 # Check that we are back where we were before: 44 frame = self.thread.GetFrameAtIndex(0) 45 self.assertTrue( 46 self.orig_frame_pc == frame.GetPC(), 47 "Restored the zeroth frame correctly") 48 49 def call_function(self): 50 (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(self, 51 'Stop here in main.', self.main_source_spec) 52 53 # Make sure the SIGCHLD behavior is pass/no-stop/no-notify: 54 self.runCmd("process handle SIGCHLD -s 0 -p 1 -n 0") 55 56 # The sigchld_no variable should be 0 at this point. 57 self.sigchld_no = target.FindFirstGlobalVariable("sigchld_no") 58 self.assertTrue( 59 self.sigchld_no.IsValid(), 60 "Got a value for sigchld_no") 61 62 self.start_sigchld_no = self.sigchld_no.GetValueAsSigned(-1) 63 self.assertTrue( 64 self.start_sigchld_no != -1, 65 "Got an actual value for sigchld_no") 66 67 options = lldb.SBExpressionOptions() 68 # processing 30 signals takes a while, increase the expression timeout 69 # a bit 70 options.SetTimeoutInMicroSeconds(3000000) # 3s 71 options.SetUnwindOnError(True) 72 73 frame = self.thread.GetFrameAtIndex(0) 74 # Store away the PC to check that the functions unwind to the right 75 # place after calls 76 self.orig_frame_pc = frame.GetPC() 77 78 num_sigchld = 30 79 value = frame.EvaluateExpression( 80 "call_me (%d)" % 81 (num_sigchld), options) 82 self.assertTrue(value.IsValid()) 83 self.assertSuccess(value.GetError()) 84 self.assertEquals(value.GetValueAsSigned(-1), num_sigchld) 85 86 self.check_after_call(num_sigchld) 87 88 # Okay, now try with a breakpoint in the called code in the case where 89 # we are ignoring breakpoint hits. 90 handler_bkpt = target.BreakpointCreateBySourceRegex( 91 "Got sigchld %d.", self.main_source_spec) 92 self.assertTrue(handler_bkpt.GetNumLocations() > 0) 93 options.SetIgnoreBreakpoints(True) 94 options.SetUnwindOnError(True) 95 96 value = frame.EvaluateExpression( 97 "call_me (%d)" % 98 (num_sigchld), options) 99 100 self.assertTrue(value.IsValid()) 101 self.assertSuccess(value.GetError()) 102 self.assertEquals(value.GetValueAsSigned(-1), num_sigchld) 103 self.check_after_call(num_sigchld) 104 105 # Now set the signal to print but not stop and make sure that calling 106 # still works: 107 self.runCmd("process handle SIGCHLD -s 0 -p 1 -n 1") 108 109 value = frame.EvaluateExpression( 110 "call_me (%d)" % 111 (num_sigchld), options) 112 113 self.assertTrue(value.IsValid()) 114 self.assertSuccess(value.GetError()) 115 self.assertEquals(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 119 # complete the call: 120 options.SetUnwindOnError(False) 121 value = frame.EvaluateExpression( 122 "call_me (%d)" % 123 (num_sigchld), options) 124 125 self.assertTrue(value.IsValid()) 126 self.assertSuccess(value.GetError()) 127 self.assertEquals(value.GetValueAsSigned(-1), num_sigchld) 128 self.check_after_call(num_sigchld) 129 130 # Okay, now set UnwindOnError to true, and then make the signal behavior to stop 131 # and see that now we do stop at the signal point: 132 133 self.runCmd("process handle SIGCHLD -s 1 -p 1 -n 1") 134 135 value = frame.EvaluateExpression( 136 "call_me (%d)" % 137 (num_sigchld), options) 138 self.assertTrue(value.IsValid()) 139 self.assertFalse(value.GetError().Success()) 140 141 # Set signal handling back to no-stop, and continue and we should end 142 # up back in out starting frame: 143 self.runCmd("process handle SIGCHLD -s 0 -p 1 -n 1") 144 145 error = process.Continue() 146 self.assertSuccess(error, 147 "Continuing after stopping for signal succeeds.") 148 149 frame = self.thread.GetFrameAtIndex(0) 150 self.assertTrue( 151 frame.GetPC() == self.orig_frame_pc, 152 "Continuing returned to the place we started.") 153