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