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