1"""
2Test thread creation after process attach.
3"""
4
5
6
7import lldb
8from lldbsuite.test.decorators import *
9from lldbsuite.test.lldbtest import *
10from lldbsuite.test import lldbutil
11
12
13class CreateAfterAttachTestCase(TestBase):
14
15    mydir = TestBase.compute_mydir(__file__)
16
17    def setUp(self):
18        # Call super's setUp().
19        TestBase.setUp(self)
20        # Find the line numbers for our breakpoints.
21        self.break_1 = line_number('main.cpp', '// Set first breakpoint here')
22        self.break_2 = line_number('main.cpp', '// Set second breakpoint here')
23        self.break_3 = line_number('main.cpp', '// Set third breakpoint here')
24
25    # Occasionally hangs on Windows, may be same as other issues.
26    @skipIfWindows
27    @skipIfiOSSimulator
28    @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr48376")
29    @expectedFailureNetBSD
30    def test_create_after_attach(self):
31        """Test thread creation after process attach."""
32        self.build(dictionary=self.getBuildFlags(use_cpp11=False))
33        exe = self.getBuildArtifact("a.out")
34
35        # Spawn a new process
36        popen = self.spawnSubprocess(exe)
37        pid = popen.pid
38
39        # Attach to the spawned process
40        self.runCmd("process attach -p " + str(pid))
41
42        target = self.dbg.GetSelectedTarget()
43
44        process = target.GetProcess()
45        self.assertTrue(process, PROCESS_IS_VALID)
46
47        # This should create a breakpoint in the main thread.
48        lldbutil.run_break_set_by_file_and_line(
49            self, "main.cpp", self.break_1, num_expected_locations=1)
50
51        # This should create a breakpoint in the second child thread.
52        lldbutil.run_break_set_by_file_and_line(
53            self, "main.cpp", self.break_2, num_expected_locations=1)
54
55        # This should create a breakpoint in the first child thread.
56        lldbutil.run_break_set_by_file_and_line(
57            self, "main.cpp", self.break_3, num_expected_locations=1)
58
59        # Note:  With std::thread, we cannot rely on particular thread numbers.  Using
60        # std::thread may cause the program to spin up a thread pool (and it does on
61        # Windows), so the thread numbers are non-deterministic.
62
63        # Run to the first breakpoint
64        self.runCmd("continue")
65
66        # The stop reason of the thread should be breakpoint.
67        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
68                    substrs=['stopped',
69                             '* thread #',
70                             'main',
71                             'stop reason = breakpoint'])
72
73        # Change a variable to escape the loop
74        self.runCmd("expression main_thread_continue = 1")
75
76        # Run to the second breakpoint
77        self.runCmd("continue")
78
79        # The stop reason of the thread should be breakpoint.
80        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
81                    substrs=['stopped',
82                             '* thread #',
83                             'thread_2_func',
84                             'stop reason = breakpoint'])
85
86        # Change a variable to escape the loop
87        self.runCmd("expression child_thread_continue = 1")
88
89        # Run to the third breakpoint
90        self.runCmd("continue")
91
92        # The stop reason of the thread should be breakpoint.
93        # Thread 3 may or may not have already exited.
94        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
95                    substrs=['stopped',
96                             '* thread #',
97                             'thread_1_func',
98                             'stop reason = breakpoint'])
99
100        # Run to completion
101        self.runCmd("continue")
102
103        # At this point, the inferior process should have exited.
104        self.assertTrue(
105            process.GetState() == lldb.eStateExited,
106            PROCESS_EXITED)
107