1"""
2Test "print object" where another thread blocks the print object from making progress.
3"""
4
5from __future__ import print_function
6
7
8import lldb
9from lldbsuite.test.decorators import *
10from lldbsuite.test.lldbtest import *
11from lldbsuite.test import lldbutil
12
13
14class PrintObjTestCase(TestBase):
15
16    def setUp(self):
17        # Call super's setUp().
18        TestBase.setUp(self)
19        # My source program.
20        self.source = "blocked.m"
21        # Find the line numbers to break at.
22        self.line = line_number(self.source, '// Set a breakpoint here.')
23
24    def test_print_obj(self):
25        """
26        Test "print object" where another thread blocks the print object from making progress.
27
28        Set a breakpoint on the line in my_pthread_routine.  Then switch threads
29        to the main thread, and do print the lock_me object.  Since that will
30        try to get the lock already gotten by my_pthread_routime thread, it will
31        have to switch to running all threads, and that should then succeed.
32        """
33        d = {'EXE': 'b.out'}
34        self.build(dictionary=d)
35        self.setTearDownCleanup(dictionary=d)
36        exe = self.getBuildArtifact('b.out')
37
38        target = self.dbg.CreateTarget(exe)
39        self.assertTrue(target, VALID_TARGET)
40
41        breakpoint = target.BreakpointCreateByLocation(self.source, self.line)
42        self.assertTrue(breakpoint, VALID_BREAKPOINT)
43        self.runCmd("breakpoint list")
44
45        # Launch the process, and do not stop at the entry point.
46        process = target.LaunchSimple(
47            None, None, self.get_process_working_directory())
48
49        self.runCmd("thread backtrace all")
50
51        # Let's get the current stopped thread.  We'd like to switch to the
52        # other thread to issue our 'po lock_me' command.
53        import lldbsuite.test.lldbutil as lldbutil
54        this_thread = lldbutil.get_stopped_thread(
55            process, lldb.eStopReasonBreakpoint)
56        self.assertTrue(this_thread)
57
58        # Find the other thread.  The iteration protocol of SBProcess and the
59        # rich comparison methods (__eq__/__ne__) of SBThread come in handy.
60        other_thread = None
61        for t in process:
62            if t != this_thread:
63                other_thread = t
64                break
65
66        # Set the other thread as the selected thread to issue our 'po'
67        # command.other
68        self.assertTrue(other_thread)
69        process.SetSelectedThread(other_thread)
70        if self.TraceOn():
71            print("selected thread:" + lldbutil.get_description(other_thread))
72        self.runCmd("thread backtrace")
73
74        # We want to traverse the frame to the one corresponding to blocked.m to
75        # issue our 'po lock_me' command.
76
77        depth = other_thread.GetNumFrames()
78        for i in range(depth):
79            frame = other_thread.GetFrameAtIndex(i)
80            name = frame.GetFunctionName()
81            if name == 'main':
82                other_thread.SetSelectedFrame(i)
83                if self.TraceOn():
84                    print("selected frame:" + lldbutil.get_description(frame))
85                break
86
87        self.expect("po lock_me", OBJECT_PRINTED_CORRECTLY,
88                    substrs=['I am pretty special.'])
89