Author: labath Date: Mon Aug 24 08:23:48 2015 New Revision: 245838 URL: http://llvm.org/viewvc/llvm-project?rev=245838&view=rev Log: Make TestCreateDuringInstructionStep linux-specific
Summary: There were a number of issues about the way I have designed this test originally: - it relied on single-stepping through large parts of code, which was slow and unreliable - the threading libraries interfered with the exact thing we wanted to test For this reason, I have rewritted the test using low-level linux api, which allows the test to be much more focused. The functionality for other platforms will need to be tested separately. Reviewers: tberghammer Subscribers: tberghammer, danalbert, srhines, lldb-commits Differential Revision: http://reviews.llvm.org/D12280 Added: lldb/trunk/test/linux/thread/ lldb/trunk/test/linux/thread/create_during_instruction_step/ lldb/trunk/test/linux/thread/create_during_instruction_step/Makefile - copied, changed from r245831, lldb/trunk/test/functionalities/thread/create_during_instruction_step/Makefile lldb/trunk/test/linux/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py - copied, changed from r245831, lldb/trunk/test/functionalities/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py lldb/trunk/test/linux/thread/create_during_instruction_step/main.cpp Removed: lldb/trunk/test/functionalities/thread/create_during_instruction_step/Makefile lldb/trunk/test/functionalities/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py lldb/trunk/test/functionalities/thread/create_during_instruction_step/main.cpp Removed: lldb/trunk/test/functionalities/thread/create_during_instruction_step/Makefile URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/thread/create_during_instruction_step/Makefile?rev=245837&view=auto ============================================================================== --- lldb/trunk/test/functionalities/thread/create_during_instruction_step/Makefile (original) +++ lldb/trunk/test/functionalities/thread/create_during_instruction_step/Makefile (removed) @@ -1,5 +0,0 @@ -LEVEL = ../../../make - -CXX_SOURCES := main.cpp -ENABLE_THREADS := YES -include $(LEVEL)/Makefile.rules Removed: lldb/trunk/test/functionalities/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py?rev=245837&view=auto ============================================================================== --- lldb/trunk/test/functionalities/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py (original) +++ lldb/trunk/test/functionalities/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py (removed) @@ -1,91 +0,0 @@ -""" -This tests that we do not lose control of the inferior, while doing an instruction-level step -over a thread creation instruction. -""" - -import os -import unittest2 -import lldb -from lldbtest import * -import lldbutil - -class CreateDuringInstructionStepTestCase(TestBase): - - mydir = TestBase.compute_mydir(__file__) - - def setUp(self): - # Call super's setUp(). - TestBase.setUp(self) - # Find the line numbers to break and continue. - self.breakpoint = line_number('main.cpp', '// Set breakpoint here') - - @dsym_test - def test_step_inst_with_dsym(self): - self.buildDsym(dictionary=self.getBuildFlags()) - self.create_during_step_inst_test() - - @dwarf_test - @skipIfTargetAndroid(archs=['aarch64']) - @expectedFailureAndroid("llvm.org/pr23944", archs=['aarch64']) # We are unable to step through std::thread::_M_start_thread - def test_step_inst_with_dwarf(self): - self.buildDwarf(dictionary=self.getBuildFlags()) - self.create_during_step_inst_test() - - def create_during_step_inst_test(self): - exe = os.path.join(os.getcwd(), "a.out") - target = self.dbg.CreateTarget(exe) - self.assertTrue(target and target.IsValid(), "Target is valid") - - # This should create a breakpoint in the stepping thread. - self.bp_num = lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.breakpoint, num_expected_locations=-1) - - # Run the program. - process = target.LaunchSimple(None, None, self.get_process_working_directory()) - self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID) - - # The stop reason of the thread should be breakpoint. - self.assertEqual(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) - self.assertEqual(lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint).IsValid(), 1, - STOPPED_DUE_TO_BREAKPOINT) - - # Get the number of threads - num_threads = process.GetNumThreads() - - # Make sure we see only one threads - self.assertEqual(num_threads, 1, 'Number of expected threads and actual threads do not match.') - - thread = process.GetThreadAtIndex(0) - self.assertTrue(thread and thread.IsValid(), "Thread is valid") - - # Keep stepping until we see the thread creation - while process.GetNumThreads() < 2: - # This skips some functions we have trouble stepping into. Testing stepping - # through these is not the purpose of this test. We just want to find the - # instruction, which creates the thread. - if thread.GetFrameAtIndex(0).GetFunctionName() in [ - '__sync_fetch_and_add_4', # Android arm: unable to set a breakpoint for software single-step - 'pthread_mutex_lock', # Android arm: function contains atomic instruction sequences - 'pthread_mutex_unlock' # Android arm: function contains atomic instruction sequences - ]: - thread.StepOut() - else: - thread.StepInstruction(False) - self.assertEqual(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) - self.assertEqual(thread.GetStopReason(), lldb.eStopReasonPlanComplete, "Step operation succeeded") - if self.TraceOn(): - self.runCmd("disassemble --pc") - - if self.TraceOn(): - self.runCmd("thread list") - - # We have successfully caught thread creation. Now just run to completion - process.Continue() - - # At this point, the inferior process should have exited. - self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED) - -if __name__ == '__main__': - import atexit - lldb.SBDebugger.Initialize() - atexit.register(lambda: lldb.SBDebugger.Terminate()) - unittest2.main() Removed: lldb/trunk/test/functionalities/thread/create_during_instruction_step/main.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/thread/create_during_instruction_step/main.cpp?rev=245837&view=auto ============================================================================== --- lldb/trunk/test/functionalities/thread/create_during_instruction_step/main.cpp (original) +++ lldb/trunk/test/functionalities/thread/create_during_instruction_step/main.cpp (removed) @@ -1,36 +0,0 @@ -//===-- main.cpp ------------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include <atomic> -#include <thread> - -std::atomic<bool> flag(false); - -void do_nothing() -{ - while (flag) - ; -} - -int main () -{ - // Instruction-level stepping over a creation of the first thread takes a very long time, so - // we give the threading machinery a chance to initialize all its data structures. - // This way, stepping over the second thread will be much faster. - std::thread dummy(do_nothing); - dummy.join(); - - // Make sure the new thread does not exit before we get a chance to notice the main thread stopped - flag = true; - - std::thread thread(do_nothing); // Set breakpoint here - flag = false; // Release the new thread. - thread.join(); - return 0; -} Copied: lldb/trunk/test/linux/thread/create_during_instruction_step/Makefile (from r245831, lldb/trunk/test/functionalities/thread/create_during_instruction_step/Makefile) URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/linux/thread/create_during_instruction_step/Makefile?p2=lldb/trunk/test/linux/thread/create_during_instruction_step/Makefile&p1=lldb/trunk/test/functionalities/thread/create_during_instruction_step/Makefile&r1=245831&r2=245838&rev=245838&view=diff ============================================================================== (empty) Copied: lldb/trunk/test/linux/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py (from r245831, lldb/trunk/test/functionalities/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py) URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/linux/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py?p2=lldb/trunk/test/linux/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py&p1=lldb/trunk/test/functionalities/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py&r1=245831&r2=245838&rev=245838&view=diff ============================================================================== --- lldb/trunk/test/functionalities/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py (original) +++ lldb/trunk/test/linux/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py Mon Aug 24 08:23:48 2015 @@ -16,8 +16,6 @@ class CreateDuringInstructionStepTestCas def setUp(self): # Call super's setUp(). TestBase.setUp(self) - # Find the line numbers to break and continue. - self.breakpoint = line_number('main.cpp', '// Set breakpoint here') @dsym_test def test_step_inst_with_dsym(self): @@ -25,8 +23,6 @@ class CreateDuringInstructionStepTestCas self.create_during_step_inst_test() @dwarf_test - @skipIfTargetAndroid(archs=['aarch64']) - @expectedFailureAndroid("llvm.org/pr23944", archs=['aarch64']) # We are unable to step through std::thread::_M_start_thread def test_step_inst_with_dwarf(self): self.buildDwarf(dictionary=self.getBuildFlags()) self.create_during_step_inst_test() @@ -37,7 +33,8 @@ class CreateDuringInstructionStepTestCas self.assertTrue(target and target.IsValid(), "Target is valid") # This should create a breakpoint in the stepping thread. - self.bp_num = lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.breakpoint, num_expected_locations=-1) + breakpoint = target.BreakpointCreateByName("main") + self.assertTrue(breakpoint and breakpoint.IsValid(), "Breakpoint is valid") # Run the program. process = target.LaunchSimple(None, None, self.get_process_working_directory()) @@ -45,31 +42,19 @@ class CreateDuringInstructionStepTestCas # The stop reason of the thread should be breakpoint. self.assertEqual(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) - self.assertEqual(lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint).IsValid(), 1, - STOPPED_DUE_TO_BREAKPOINT) - # Get the number of threads - num_threads = process.GetNumThreads() + threads = lldbutil.get_threads_stopped_at_breakpoint(process, breakpoint) + self.assertEquals(len(threads), 1, STOPPED_DUE_TO_BREAKPOINT) - # Make sure we see only one threads - self.assertEqual(num_threads, 1, 'Number of expected threads and actual threads do not match.') - - thread = process.GetThreadAtIndex(0) + thread = threads[0] self.assertTrue(thread and thread.IsValid(), "Thread is valid") + # Make sure we see only one threads + self.assertEqual(process.GetNumThreads(), 1, 'Number of expected threads and actual threads do not match.') + # Keep stepping until we see the thread creation while process.GetNumThreads() < 2: - # This skips some functions we have trouble stepping into. Testing stepping - # through these is not the purpose of this test. We just want to find the - # instruction, which creates the thread. - if thread.GetFrameAtIndex(0).GetFunctionName() in [ - '__sync_fetch_and_add_4', # Android arm: unable to set a breakpoint for software single-step - 'pthread_mutex_lock', # Android arm: function contains atomic instruction sequences - 'pthread_mutex_unlock' # Android arm: function contains atomic instruction sequences - ]: - thread.StepOut() - else: - thread.StepInstruction(False) + thread.StepInstruction(False) self.assertEqual(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED) self.assertEqual(thread.GetStopReason(), lldb.eStopReasonPlanComplete, "Step operation succeeded") if self.TraceOn(): Added: lldb/trunk/test/linux/thread/create_during_instruction_step/main.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/linux/thread/create_during_instruction_step/main.cpp?rev=245838&view=auto ============================================================================== --- lldb/trunk/test/linux/thread/create_during_instruction_step/main.cpp (added) +++ lldb/trunk/test/linux/thread/create_during_instruction_step/main.cpp Mon Aug 24 08:23:48 2015 @@ -0,0 +1,55 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// This file deliberately uses low level linux-specific API for thread creation because: +// - instruction-stepping over thread creation using higher-level functions was very slow +// - it was also unreliable due to single-stepping bugs unrelated to this test +// - some threading libraries do not create or destroy threads when we would expect them to + +#include <sched.h> + +#include <atomic> +#include <cstdio> + +enum { STACK_SIZE = 0x2000 }; + +static uint8_t child_stack[STACK_SIZE]; + +pid_t child_tid; + +std::atomic<bool> flag(false); + +int thread_main(void *) +{ + while (! flag) // Make sure the thread does not exit prematurely + ; + + return 0; +} + +int main () +{ + int ret = clone(thread_main, + child_stack + STACK_SIZE/2, // Don't care whether the stack grows up or down, + // just point to the middle + CLONE_CHILD_CLEARTID | CLONE_FILES | CLONE_FS | CLONE_PARENT_SETTID | CLONE_SETTLS | + CLONE_SIGHAND | CLONE_SYSVSEM | CLONE_THREAD | CLONE_VM, + nullptr, // thread_main argument + &child_tid); + + if (ret == -1) + { + perror("clone"); + return 1; + } + + flag = true; + + return 0; +} _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits