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