diff options
Diffstat (limited to 'lldb/packages/Python/lldbsuite/test')
5 files changed, 223 insertions, 6 deletions
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_all/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_all/Makefile new file mode 100644 index 00000000000..90ec8b9d913 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_all/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +CXXFLAGS += -std=c++11 +CXX_SOURCES := ParallelTask.cpp +ENABLE_STD_THREADS := YES +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_all/ParallelTask.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_all/ParallelTask.cpp new file mode 100755 index 00000000000..71fb8e3bb56 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_all/ParallelTask.cpp @@ -0,0 +1,151 @@ +#include <cstdint> +#include <thread> +#include <vector> +#include <queue> +#include <future> +#include <iostream> +#include <cassert> + +class TaskPoolImpl +{ +public: + TaskPoolImpl(uint32_t num_threads) : + m_stop(false) + { + for (uint32_t i = 0; i < num_threads; ++i) + m_threads.emplace_back(Worker, this); + } + + ~TaskPoolImpl() + { + Stop(); + } + + template<typename F, typename... Args> + std::future<typename std::result_of<F(Args...)>::type> + AddTask(F&& f, Args&&... args) + { + auto task = std::make_shared<std::packaged_task<typename std::result_of<F(Args...)>::type()>>( + std::bind(std::forward<F>(f), std::forward<Args>(args)...)); + + std::unique_lock<std::mutex> lock(m_tasks_mutex); + assert(!m_stop && "Can't add task to TaskPool after it is stopped"); + m_tasks.emplace([task](){ (*task)(); }); + lock.unlock(); + m_tasks_cv.notify_one(); + + return task->get_future(); + } + + void + Stop() + { + std::unique_lock<std::mutex> lock(m_tasks_mutex); + m_stop = true; + m_tasks_mutex.unlock(); + m_tasks_cv.notify_all(); + for (auto& t : m_threads) + t.join(); + } + +private: + static void + Worker(TaskPoolImpl* pool) + { + while (true) + { + std::unique_lock<std::mutex> lock(pool->m_tasks_mutex); + if (pool->m_tasks.empty()) + pool->m_tasks_cv.wait(lock, [pool](){ return !pool->m_tasks.empty() || pool->m_stop; }); + if (pool->m_tasks.empty()) + break; + + std::function<void()> f = pool->m_tasks.front(); + pool->m_tasks.pop(); + lock.unlock(); + + f(); + } + } + + std::queue<std::function<void()>> m_tasks; + std::mutex m_tasks_mutex; + std::condition_variable m_tasks_cv; + bool m_stop; + std::vector<std::thread> m_threads; +}; + +class TaskPool +{ +public: + // Add a new task to the thread pool and return a std::future belongs for the newly created task. + // The caller of this function have to wait on the future for this task to complete. + template<typename F, typename... Args> + static std::future<typename std::result_of<F(Args...)>::type> + AddTask(F&& f, Args&&... args) + { + return GetImplementation().AddTask(std::forward<F>(f), std::forward<Args>(args)...); + } + + // Run all of the specified tasks on the thread pool and wait until all of them are finished + // before returning + template<typename... T> + static void + RunTasks(T&&... t) + { + RunTaskImpl<T...>::Run(std::forward<T>(t)...); + } + +private: + static TaskPoolImpl& + GetImplementation() + { + static TaskPoolImpl g_task_pool_impl(std::thread::hardware_concurrency()); + return g_task_pool_impl; + } + + template<typename... T> + struct RunTaskImpl; +}; + +template<typename H, typename... T> +struct TaskPool::RunTaskImpl<H, T...> +{ + static void + Run(H&& h, T&&... t) + { + auto f = AddTask(std::forward<H>(h)); + RunTaskImpl<T...>::Run(std::forward<T>(t)...); + f.wait(); + } +}; + +template<> +struct TaskPool::RunTaskImpl<> +{ + static void + Run() {} +}; + +int main() +{ + std::vector<std::future<uint32_t>> tasks; + for (int i = 0; i < 100000; ++i) + { + tasks.emplace_back(TaskPool::AddTask([](int i){ + uint32_t s = 0; + for (int j = 0; j <= i; ++j) + s += j; + return s; + }, + i)); + } + + for (auto& it : tasks) // Set breakpoint here + it.wait(); + + TaskPool::RunTasks( + []() { return 1; }, + []() { return "aaaa"; } + ); +} diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_all/TestBacktraceAll.py b/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_all/TestBacktraceAll.py new file mode 100644 index 00000000000..d4000548b2c --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/thread/backtrace_all/TestBacktraceAll.py @@ -0,0 +1,54 @@ +""" +Test regression for Bug 25251. +""" + +import os, time +import unittest2 +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class BreakpointAfterJoinTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number for our breakpoint. + self.breakpoint = line_number('ParallelTask.cpp', '// Set breakpoint here') + + def test(self): + """Test breakpoint handling after a thread join.""" + self.build(dictionary=self.getBuildFlags()) + + exe = os.path.join(os.getcwd(), "a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # This should create a breakpoint + lldbutil.run_break_set_by_file_and_line (self, "ParallelTask.cpp", self.breakpoint, num_expected_locations=-1) + + # The breakpoint list should show 1 location. + self.expect("breakpoint list -f", "Breakpoint location shown correctly", + substrs = ["1: file = 'ParallelTask.cpp', line = %d, exact_match = 0" % self.breakpoint]) + + # Run the program. + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + # This should not result in a segmentation fault + self.expect("thread backtrace all", STOPPED_DUE_TO_BREAKPOINT, + substrs = ["stop reason = breakpoint 1."]) + + # Run to completion + self.runCmd("continue") + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() diff --git a/lldb/packages/Python/lldbsuite/test/lang/c/typedef/Testtypedef.py b/lldb/packages/Python/lldbsuite/test/lang/c/typedef/Testtypedef.py index 9a73f851759..594c0528963 100644 --- a/lldb/packages/Python/lldbsuite/test/lang/c/typedef/Testtypedef.py +++ b/lldb/packages/Python/lldbsuite/test/lang/c/typedef/Testtypedef.py @@ -32,7 +32,7 @@ class TypedefTestCase(TestBase): """Test 'image lookup -t a' at different scopes and check for correct display.""" exe = os.path.join(os.getcwd(), "a.out") self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) - typearray = ("float", "float", "char", "float", "int", "double", "float", "float") + typearray = ("float", "float", "char", "double *", "float", "int", "double", "float", "float") arraylen = len(typearray)+1 for i in range(1,arraylen): loc_line = line_number('main.c', '// Set break point ' + str(i) + '.') diff --git a/lldb/packages/Python/lldbsuite/test/lang/c/typedef/main.c b/lldb/packages/Python/lldbsuite/test/lang/c/typedef/main.c index 6c13affbbc1..62f8a00e664 100644 --- a/lldb/packages/Python/lldbsuite/test/lang/c/typedef/main.c +++ b/lldb/packages/Python/lldbsuite/test/lang/c/typedef/main.c @@ -6,6 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +void test() +{ + typedef double * a; + a b = 0; // Set break point 4. +} int main (int argc, char const *argv[]) { typedef float a; @@ -16,25 +21,26 @@ int main (int argc, char const *argv[]) typedef char a; i++; a charvariable = 'a'; // Set break point 3. + test(); } { int c = 0; - c++; // Set break point 4. + c++; // Set break point 5. for(i = 0 ; i < 1 ; i++) { typedef int a; a b; - b = 7; // Set break point 5. + b = 7; // Set break point 6. } for(i = 0 ; i < 1 ; i++) { typedef double a; a b; - b = 3.14; // Set break point 6. + b = 3.14; // Set break point 7. } - c = 1; // Set break point 7. + c = 1; // Set break point 8. } floatvariable = 2.5; - floatvariable = 2.8; // Set break point 8. + floatvariable = 2.8; // Set break point 9. return 0; } |