xref: /llvm-project/lldb/test/API/commands/process/handle/TestProcessHandle.py (revision 2238dcc39358353cac21df75c3c3286ab20b8f53)
1import lldb
2from lldbsuite.test.lldbtest import *
3from lldbsuite.test import lldbutil
4from lldbsuite.test.decorators import *
5
6
7class TestProcessHandle(TestBase):
8    @no_debug_info_test
9    @skipIfWindows
10    def test_process_handle(self):
11        """Test that calling process handle before we have a target, and before we
12        have a process will affect the process.  Also that the signal settings
13        are preserved on rerun."""
14        self.build()
15
16        # Make sure we don't accept signal values by signo with no process - we don't know what the
17        # mapping will be so we can't do the right thing with bare numbers:
18        lldbutil.set_actions_for_signal(
19            self, "9", "true", None, None, expect_success=False
20        )
21
22        # First, I need a reference value so I can see whether changes actually took:
23        (target, process, _, bkpt) = lldbutil.run_to_source_breakpoint(
24            self, "// break here", lldb.SBFileSpec("main.cpp")
25        )
26        (default_pass, default_stop, default_notify) = lldbutil.get_actions_for_signal(
27            self, "SIGSEGV"
28        )
29
30        # Let's change the value here, then exit and make sure the changed value sticks:
31        new_value = "false"
32        if default_pass == "true":
33            new_value = "false"
34
35        # First make sure we get an error for bogus values when running:
36        lldbutil.set_actions_for_signal(
37            self, "NOTSIGSEGV", new_value, None, None, expect_success=False
38        )
39
40        # Then set the one we intend to change.
41        lldbutil.set_actions_for_signal(self, "SIGSEGV", new_value, None, None)
42
43        process.Continue()
44
45        self.assertState(process.GetState(), lldb.eStateExited)
46        self.assertEqual(process.GetExitStatus(), 0)
47
48        # Check that we preserved the setting:
49        (curr_pass, curr_stop, curr_notify) = lldbutil.get_actions_for_signal(
50            self, "SIGSEGV", from_target=True
51        )
52        self.assertEqual(curr_pass, new_value, "Pass was set correctly")
53        self.assertEqual(curr_stop, "not set", "Stop was not set by us")
54        self.assertEqual(curr_notify, "not set", "Notify was not set by us")
55
56        # Run again and make sure that we prime the new process with these settings:
57        process = lldbutil.run_to_breakpoint_do_run(self, target, bkpt)
58
59        # We check the process settings now, to see what got copied into the process:
60        (curr_pass, curr_stop, curr_notify) = lldbutil.get_actions_for_signal(
61            self, "SIGSEGV"
62        )
63        self.assertEqual(curr_pass, new_value, "Pass was set correctly")
64        self.assertEqual(curr_stop, default_stop, "Stop was its default value")
65        self.assertEqual(curr_notify, default_notify, "Notify was its default value")
66
67        # Now kill this target, set the handling and make sure the values get copied from the dummy into the new target.
68        success = self.dbg.DeleteTarget(target)
69        self.assertTrue(success, "Deleted the target")
70        self.assertEqual(self.dbg.GetNumTargets(), 0, "We did delete all the targets.")
71
72        # The signal settings should be back at their default - we were only setting this on the target:
73        lldbutil.get_actions_for_signal(
74            self, "SIGSEGV", from_target=True, expected_absent=True
75        )
76        # Set a valid one:
77        lldbutil.set_actions_for_signal(self, "SIGSEGV", new_value, None, None)
78        # Set a bogus one - we don't have a way to check pre-run so this is allowed
79        # but we should get an error message when launching:
80        lldbutil.set_actions_for_signal(self, "SIGNOTSIG", new_value, None, None)
81
82        out_filename = self.getBuildArtifact("output")
83        success = True
84        try:
85            f = open(out_filename, "w")
86        except:
87            success = False
88
89        if not success:
90            self.fail("Couldn't open error output file for writing.")
91
92        self.dbg.SetErrorFileHandle(f, False)
93        # Now make a new process and make sure the right values got copied into the new target
94        (target, process, _, bkpt) = lldbutil.run_to_source_breakpoint(
95            self, "// break here", lldb.SBFileSpec("main.cpp")
96        )
97        f.write("TESTPATTERN\n")
98        f.flush()
99        f.close()
100
101        try:
102            f = open(out_filename, "r")
103        except:
104            success = False
105
106        if not success:
107            self.fail("Couldn't open error output file for reading")
108        errors = f.read()
109        f.close()
110
111        self.assertIn("SIGNOTSIG", errors, "We warned about the unset signal")
112        # Also make sure we didn't accidentally add this bogus setting to the process.
113        lldbutil.set_actions_for_signal(
114            self, "SIGNOTSIG", "true", "true", "true", expect_success=False
115        )
116
117        # Check that they went into the target:
118        (curr_pass, curr_stop, curr_notify) = lldbutil.get_actions_for_signal(
119            self, "SIGSEGV", from_target=True
120        )
121        self.assertEqual(curr_pass, new_value, "Pass was set correctly")
122        self.assertEqual(curr_stop, "not set", "Stop was not set by us")
123        self.assertEqual(curr_notify, "not set", "Notify was not set by us")
124
125        # And the process:
126        # Check that they went into the target:
127        (curr_pass, curr_stop, curr_notify) = lldbutil.get_actions_for_signal(
128            self, "SIGSEGV"
129        )
130        self.assertEqual(curr_pass, new_value, "Pass was set correctly")
131        self.assertEqual(curr_stop, default_stop, "Stop was its default value")
132        self.assertEqual(curr_notify, default_notify, "Notify was its default value")
133
134        # Now clear the handling, and make sure that we get the right signal values again:
135        self.runCmd("process handle -c SIGSEGV")
136        # Check that there is no longer configuration for SIGSEGV in the target:
137        lldbutil.get_actions_for_signal(
138            self, "SIGSEGV", from_target=True, expected_absent=True
139        )
140        # Make a new process, to make sure we did indeed reset the values:
141        (target, process, _, bkpt) = lldbutil.run_to_source_breakpoint(
142            self, "// break here", lldb.SBFileSpec("main.cpp")
143        )
144        (curr_pass, curr_stop, curr_notify) = lldbutil.get_actions_for_signal(
145            self, "SIGSEGV"
146        )
147        self.assertEqual(curr_pass, new_value, "Pass was set correctly")
148        self.assertEqual(curr_stop, default_stop, "Stop was its default value")
149        self.assertEqual(curr_notify, default_notify, "Notify was its default value")
150
151        # Finally remove this from the dummy target as well, and make sure it was cleared from there:
152        self.runCmd("process handle -c -d SIGSEGV")
153        error = process.Kill()
154        self.assertSuccess(error, "Killed the process")
155        success = self.dbg.DeleteTarget(target)
156        self.assertTrue(success, "Destroyed the target.")
157
158        (target, process, _, bkpt) = lldbutil.run_to_source_breakpoint(
159            self, "// break here", lldb.SBFileSpec("main.cpp")
160        )
161        (curr_pass, curr_stop, curr_notify) = lldbutil.get_actions_for_signal(
162            self, "SIGSEGV"
163        )
164        self.assertEqual(curr_pass, default_pass, "Pass was set correctly")
165        self.assertEqual(curr_stop, default_stop, "Stop was its default value")
166        self.assertEqual(curr_notify, default_notify, "Notify was its default value")
167