141 lines · python
1"""2Test calling a function that hits a signal set to auto-restart, make sure the call completes.3"""4 5 6import lldb7from lldbsuite.test.decorators import *8from lldbsuite.test.lldbtest import *9from lldbsuite.test import lldbutil10 11 12class ExprCommandThatRestartsTestCase(TestBase):13 NO_DEBUG_INFO_TESTCASE = True14 15 def setUp(self):16 # Call super's setUp().17 TestBase.setUp(self)18 19 self.main_source = "lotta-signals.c"20 self.main_source_spec = lldb.SBFileSpec(self.main_source)21 22 @skipIfDarwin # llvm.org/pr19246: intermittent failure23 @skipIfWindows # Test relies on signals, unsupported on Windows24 @expectedFlakeyAndroid(bugnumber="llvm.org/pr19246")25 @expectedFlakeyNetBSD26 def test(self):27 """Test calling function that hits a signal and restarts."""28 self.build()29 self.call_function()30 31 def check_after_call(self, num_sigchld):32 after_call = self.sigchld_no.GetValueAsSigned(-1)33 self.assertEqual(34 after_call - self.start_sigchld_no,35 num_sigchld,36 "Really got %d SIGCHLD signals through the call." % (num_sigchld),37 )38 self.start_sigchld_no = after_call39 40 # Check that we are back where we were before:41 frame = self.thread.GetFrameAtIndex(0)42 self.assertEqual(43 self.orig_frame_pc, frame.GetPC(), "Restored the zeroth frame correctly"44 )45 46 def call_function(self):47 (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(48 self, "Stop here in main.", self.main_source_spec49 )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(self.sigchld_no.IsValid(), "Got a value for sigchld_no")57 58 self.start_sigchld_no = self.sigchld_no.GetValueAsSigned(-1)59 self.assertNotEqual(60 self.start_sigchld_no, -1, "Got an actual value for sigchld_no"61 )62 63 options = lldb.SBExpressionOptions()64 # processing 30 signals takes a while, increase the expression timeout65 # a bit66 options.SetTimeoutInMicroSeconds(3000000) # 3s67 options.SetUnwindOnError(True)68 69 frame = self.thread.GetFrameAtIndex(0)70 # Store away the PC to check that the functions unwind to the right71 # place after calls72 self.orig_frame_pc = frame.GetPC()73 74 num_sigchld = 3075 value = frame.EvaluateExpression("call_me (%d)" % (num_sigchld), options)76 self.assertTrue(value.IsValid())77 self.assertSuccess(value.GetError())78 self.assertEqual(value.GetValueAsSigned(-1), num_sigchld)79 80 self.check_after_call(num_sigchld)81 82 # Okay, now try with a breakpoint in the called code in the case where83 # we are ignoring breakpoint hits.84 handler_bkpt = target.BreakpointCreateBySourceRegex(85 "Got sigchld %d.", self.main_source_spec86 )87 self.assertGreater(handler_bkpt.GetNumLocations(), 0)88 options.SetIgnoreBreakpoints(True)89 options.SetUnwindOnError(True)90 91 value = frame.EvaluateExpression("call_me (%d)" % (num_sigchld), options)92 93 self.assertTrue(value.IsValid())94 self.assertSuccess(value.GetError())95 self.assertEqual(value.GetValueAsSigned(-1), num_sigchld)96 self.check_after_call(num_sigchld)97 98 # Now set the signal to print but not stop and make sure that calling99 # still works:100 self.runCmd("process handle SIGCHLD -s 0 -p 1 -n 1")101 102 value = frame.EvaluateExpression("call_me (%d)" % (num_sigchld), options)103 104 self.assertTrue(value.IsValid())105 self.assertSuccess(value.GetError())106 self.assertEqual(value.GetValueAsSigned(-1), num_sigchld)107 self.check_after_call(num_sigchld)108 109 # Now set this unwind on error to false, and make sure that we still110 # complete the call:111 options.SetUnwindOnError(False)112 value = frame.EvaluateExpression("call_me (%d)" % (num_sigchld), options)113 114 self.assertTrue(value.IsValid())115 self.assertSuccess(value.GetError())116 self.assertEqual(value.GetValueAsSigned(-1), num_sigchld)117 self.check_after_call(num_sigchld)118 119 # Okay, now set UnwindOnError to true, and then make the signal behavior to stop120 # and see that now we do stop at the signal point:121 122 self.runCmd("process handle SIGCHLD -s 1 -p 1 -n 1")123 124 value = frame.EvaluateExpression("call_me (%d)" % (num_sigchld), options)125 self.assertTrue(value.IsValid())126 self.assertFalse(value.GetError().Success())127 128 # Set signal handling back to no-stop, and continue and we should end129 # up back in out starting frame:130 self.runCmd("process handle SIGCHLD -s 0 -p 1 -n 1")131 132 error = process.Continue()133 self.assertSuccess(error, "Continuing after stopping for signal succeeds.")134 135 frame = self.thread.GetFrameAtIndex(0)136 self.assertEqual(137 frame.GetPC(),138 self.orig_frame_pc,139 "Continuing returned to the place we started.",140 )141