1dbbed971SJim Ingham""" 2dbbed971SJim InghamMake sure that we handle an expression on a thread, if 3dbbed971SJim Inghamthe thread exits while the expression is running. 4dbbed971SJim Ingham""" 5dbbed971SJim Ingham 6dbbed971SJim Inghamimport lldb 7dbbed971SJim Inghamfrom lldbsuite.test.decorators import * 8dbbed971SJim Inghamimport lldbsuite.test.lldbutil as lldbutil 9dbbed971SJim Inghamfrom lldbsuite.test.lldbtest import * 10dbbed971SJim Ingham 11dbbed971SJim Inghamclass TestExitDuringExpression(TestBase): 12dbbed971SJim Ingham 13dbbed971SJim Ingham NO_DEBUG_INFO_TESTCASE = True 14dbbed971SJim Ingham 15dbbed971SJim Ingham @skipIfWindows 167dd76cccSMuhammad Omair Javaid @skipIf(oslist=["linux"], archs=["arm", "aarch64"], bugnumber="llvm.org/pr48414") 17266c90feSMichał Górny @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr48414") 1899562332SMichał Górny @expectedFailureNetBSD 19dbbed971SJim Ingham def test_exit_before_one_thread_unwind(self): 20dbbed971SJim Ingham """Test the case where we exit within the one thread timeout""" 21dbbed971SJim Ingham self.exiting_expression_test(True, True) 22dbbed971SJim Ingham 23dbbed971SJim Ingham @skipIfWindows 2428058d4cSMuhammad Omair Javaid @skipIf(oslist=["linux"], archs=["arm", "aarch64"], bugnumber="llvm.org/pr48414") 25266c90feSMichał Górny @expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr48414") 2699562332SMichał Górny @expectedFailureNetBSD 27dbbed971SJim Ingham def test_exit_before_one_thread_no_unwind(self): 28dbbed971SJim Ingham """Test the case where we exit within the one thread timeout""" 29dbbed971SJim Ingham self.exiting_expression_test(True, False) 30dbbed971SJim Ingham 31dbbed971SJim Ingham @skipIfWindows 32dbbed971SJim Ingham def test_exit_after_one_thread_unwind(self): 33dbbed971SJim Ingham """Test the case where we exit within the one thread timeout""" 34dbbed971SJim Ingham self.exiting_expression_test(False, True) 35dbbed971SJim Ingham 36dbbed971SJim Ingham @skipIfWindows 37dbbed971SJim Ingham def test_exit_after_one_thread_no_unwind(self): 38dbbed971SJim Ingham """Test the case where we exit within the one thread timeout""" 39dbbed971SJim Ingham self.exiting_expression_test(False, False) 40dbbed971SJim Ingham 41dbbed971SJim Ingham def setUp(self): 42dbbed971SJim Ingham TestBase.setUp(self) 43dbbed971SJim Ingham self.main_source_file = lldb.SBFileSpec("main.c") 44dbbed971SJim Ingham self.build() 45dbbed971SJim Ingham 46dbbed971SJim Ingham def exiting_expression_test(self, before_one_thread_timeout , unwind): 47dbbed971SJim Ingham """function_to_call sleeps for g_timeout microseconds, then calls pthread_exit. 48dbbed971SJim Ingham This test calls function_to_call with an overall timeout of 500 49dbbed971SJim Ingham microseconds, and a one_thread_timeout as passed in. 50dbbed971SJim Ingham It also sets unwind_on_exit for the call to the unwind passed in. 51dbbed971SJim Ingham This allows you to have the thread exit either before the one thread 52dbbed971SJim Ingham timeout is passed. """ 53dbbed971SJim Ingham 54dbbed971SJim Ingham (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, 55dbbed971SJim Ingham "Break here and cause the thread to exit", self.main_source_file) 56dbbed971SJim Ingham 57dbbed971SJim Ingham # We'll continue to this breakpoint after running our expression: 58dbbed971SJim Ingham return_bkpt = target.BreakpointCreateBySourceRegex("Break here to make sure the thread exited", self.main_source_file) 59dbbed971SJim Ingham frame = thread.frames[0] 60dbbed971SJim Ingham tid = thread.GetThreadID() 61dbbed971SJim Ingham # Find the timeout: 62dbbed971SJim Ingham var_options = lldb.SBVariablesOptions() 63dbbed971SJim Ingham var_options.SetIncludeArguments(False) 64dbbed971SJim Ingham var_options.SetIncludeLocals(False) 65dbbed971SJim Ingham var_options.SetIncludeStatics(True) 66dbbed971SJim Ingham 67dbbed971SJim Ingham value_list = frame.GetVariables(var_options) 68dbbed971SJim Ingham g_timeout = value_list.GetFirstValueByName("g_timeout") 69dbbed971SJim Ingham self.assertTrue(g_timeout.IsValid(), "Found g_timeout") 70dbbed971SJim Ingham 71dbbed971SJim Ingham error = lldb.SBError() 72dbbed971SJim Ingham timeout_value = g_timeout.GetValueAsUnsigned(error) 73*779bbbf2SDave Lee self.assertSuccess(error, "Couldn't get timeout value") 74dbbed971SJim Ingham 75dbbed971SJim Ingham one_thread_timeout = 0 76dbbed971SJim Ingham if (before_one_thread_timeout): 77dbbed971SJim Ingham one_thread_timeout = timeout_value * 2 78dbbed971SJim Ingham else: 79dbbed971SJim Ingham one_thread_timeout = int(timeout_value / 2) 80dbbed971SJim Ingham 81dbbed971SJim Ingham options = lldb.SBExpressionOptions() 82dbbed971SJim Ingham options.SetUnwindOnError(unwind) 83dbbed971SJim Ingham options.SetOneThreadTimeoutInMicroSeconds(one_thread_timeout) 84dbbed971SJim Ingham options.SetTimeoutInMicroSeconds(4 * timeout_value) 85dbbed971SJim Ingham 86dbbed971SJim Ingham result = frame.EvaluateExpression("function_to_call()", options) 87dbbed971SJim Ingham 88dbbed971SJim Ingham # Make sure the thread actually exited: 89dbbed971SJim Ingham thread = process.GetThreadByID(tid) 90dbbed971SJim Ingham self.assertFalse(thread.IsValid(), "The thread exited") 91dbbed971SJim Ingham 92dbbed971SJim Ingham # Make sure the expression failed: 93dbbed971SJim Ingham self.assertFalse(result.GetError().Success(), "Expression failed.") 94dbbed971SJim Ingham 95dbbed971SJim Ingham # Make sure we can keep going: 96dbbed971SJim Ingham threads = lldbutil.continue_to_breakpoint(process, return_bkpt) 97dbbed971SJim Ingham if not threads: 98dbbed971SJim Ingham self.fail("didn't get any threads back after continuing") 99dbbed971SJim Ingham 100dbbed971SJim Ingham self.assertEqual(len(threads), 1, "One thread hit our breakpoint") 101dbbed971SJim Ingham thread = threads[0] 102dbbed971SJim Ingham frame = thread.frames[0] 103dbbed971SJim Ingham # Now get the return value, if we successfully caused the thread to exit 104dbbed971SJim Ingham # it should be 10, not 20. 105dbbed971SJim Ingham ret_val = frame.FindVariable("ret_val") 106*779bbbf2SDave Lee self.assertSuccess(ret_val.GetError(), "Found ret_val") 107dbbed971SJim Ingham ret_val_value = ret_val.GetValueAsSigned(error) 108*779bbbf2SDave Lee self.assertSuccess(error, "Got ret_val's value") 109dbbed971SJim Ingham self.assertEqual(ret_val_value, 10, "We put the right value in ret_val") 110