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