<div dir="ltr">Yeah I think the stress of running the stress test along with multi-core debugging causes this one to get *really* stressed :-)<div><br></div><div>Greg and I have briefly kicked around an idea of having a marker for tests that are load-sensitive or otherwise should run at a time when none of the other tests are running.  This is likely one we'd want to bucket that way.  I'll have more to say about that when I can throw some cycles at it.</div>
</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Jul 9, 2014 at 7:17 PM, Jason Molenda <span dir="ltr"><<a href="mailto:jmolenda@apple.com" target="_blank">jmolenda@apple.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: jmolenda<br>
Date: Wed Jul  9 21:17:31 2014<br>
New Revision: 212671<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=212671&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=212671&view=rev</a><br>
Log:<br>
Add a new test in api/multiple-debuggers which tries to create 50<br>
debug sessions simultaneously to expose race conditoin/locking<br>
issues.<br>
<br>
This directory has an inferior program, testprog.cpp that has a<br>
couple of functions we can put breakpoints on.<br>
<br>
It has a driver program, multi-process-driver.cpp, which links<br>
against the LLDB solib and uses the SB APIs.  It creates 50 pthreads,<br>
creates a debugger on all of them, launches a debug session of the<br>
inferior testprog, hits a couple breakpoints, walks the stack,<br>
continues, etc., and then kills the inferior and ends the debug<br>
session.<br>
<br>
A pass is if all fifty debug sessions complete successfully<br>
in the alloted time (~60 seconds).<br>
<br>
We may need to tweak this one to work correctly on different<br>
platforms/targets but I wanted to get it checked in to start.<br>
<br>
<br>
Added:<br>
    lldb/trunk/test/api/multiple-debuggers/<br>
    lldb/trunk/test/api/multiple-debuggers/Makefile<br>
    lldb/trunk/test/api/multiple-debuggers/TestMultipleDebuggers.py<br>
    lldb/trunk/test/api/multiple-debuggers/multi-process-driver.cpp<br>
    lldb/trunk/test/api/multiple-debuggers/testprog.cpp<br>
<br>
Added: lldb/trunk/test/api/multiple-debuggers/Makefile<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/test/api/multiple-debuggers/Makefile?rev=212671&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/test/api/multiple-debuggers/Makefile?rev=212671&view=auto</a><br>

==============================================================================<br>
--- lldb/trunk/test/api/multiple-debuggers/Makefile (added)<br>
+++ lldb/trunk/test/api/multiple-debuggers/Makefile Wed Jul  9 21:17:31 2014<br>
@@ -0,0 +1,7 @@<br>
+LEVEL = ../../make<br>
+<br>
+MAKE_DSYM := NO<br>
+<br>
+CXX_SOURCES := multi-process-driver.cpp testprog.cpp<br>
+<br>
+include $(LEVEL)/Makefile.rules<br>
<br>
Added: lldb/trunk/test/api/multiple-debuggers/TestMultipleDebuggers.py<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/test/api/multiple-debuggers/TestMultipleDebuggers.py?rev=212671&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/test/api/multiple-debuggers/TestMultipleDebuggers.py?rev=212671&view=auto</a><br>

==============================================================================<br>
--- lldb/trunk/test/api/multiple-debuggers/TestMultipleDebuggers.py (added)<br>
+++ lldb/trunk/test/api/multiple-debuggers/TestMultipleDebuggers.py Wed Jul  9 21:17:31 2014<br>
@@ -0,0 +1,46 @@<br>
+"""Test the lldb public C++ api when doing multiple debug sessions simultaneously."""<br>
+<br>
+import os, re, StringIO<br>
+import unittest2<br>
+from lldbtest import *<br>
+import lldbutil<br>
+import lldb<br>
+import subprocess<br>
+<br>
+class TestMultipleSimultaneousDebuggers(TestBase):<br>
+<br>
+    mydir = TestBase.compute_mydir(__file__)<br>
+<br>
+    def setUp(self):<br>
+        TestBase.setUp(self)<br>
+        self.lib_dir = os.environ["LLDB_LIB_DIR"]<br>
+<br>
+    @skipIfi386<br>
+    def test_whatever(self):<br>
+<br>
+        self.driver_exe = os.path.join(os.getcwd(), "multi-process-driver")<br>
+        self.buildDriver('multi-process-driver.cpp', self.driver_exe)<br>
+        self.addTearDownHook(lambda: os.remove(self.driver_exe))<br>
+<br>
+        self.inferior_exe = os.path.join(os.getcwd(), "testprog")<br>
+        self.buildDriver('testprog.cpp', self.inferior_exe)<br>
+        self.addTearDownHook(lambda: os.remove(self.inferior_exe))<br>
+<br>
+        env = {self.dylibPath : self.getLLDBLibraryEnvVal()}<br>
+<br>
+# check_call will raise a CalledProcessError if multi-process-driver doesn't return<br>
+# exit code 0 to indicate success.  We can let this exception go - the test harness<br>
+# will recognize it as a test failure.<br>
+<br>
+        if self.TraceOn():<br>
+            print "Running test %s" % self.driver_exe<br>
+            check_call([self.driver_exe, self.inferior_exe], env=env)<br>
+        else:<br>
+            with open(os.devnull, 'w') as fnull:<br>
+                check_call([self.driver_exe, self.inferior_exe], env=env, stdout=fnull, stderr=fnull)<br>
+<br>
+if __name__ == '__main__':<br>
+    import atexit<br>
+    lldb.SBDebugger.Initialize()<br>
+    atexit.register(lambda: lldb.SBDebugger.Terminate())<br>
+    unittest2.main()<br>
<br>
Added: lldb/trunk/test/api/multiple-debuggers/multi-process-driver.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/test/api/multiple-debuggers/multi-process-driver.cpp?rev=212671&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/test/api/multiple-debuggers/multi-process-driver.cpp?rev=212671&view=auto</a><br>

==============================================================================<br>
--- lldb/trunk/test/api/multiple-debuggers/multi-process-driver.cpp (added)<br>
+++ lldb/trunk/test/api/multiple-debuggers/multi-process-driver.cpp Wed Jul  9 21:17:31 2014<br>
@@ -0,0 +1,265 @@<br>
+#include <stdio.h><br>
+#include <stdlib.h><br>
+<br>
+<br>
+#ifdef __APPLE__<br>
+#include <LLDB/LLDB.h><br>
+#include <LLDB/SBCommandInterpreter.h><br>
+#include <LLDB/SBCommandReturnObject.h><br>
+#include <LLDB/SBDebugger.h><br>
+#else<br>
+#include "lldb/API/LLDB.h"<br>
+#include <lldb/API/SBCommandInterpreter.h><br>
+#include <lldb/API/SBCommandReturnObject.h><br>
+#include <lldb/API/SBDebugger.h><br>
+#endif<br>
+<br>
+#define NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS 50<br>
+<br>
+#define DEBUG 0<br>
+<br>
+using namespace lldb;<br>
+<br>
+bool *completed_threads_array = 0;<br>
+bool *successful_threads_array  = 0;<br>
+<br>
+bool<br>
+wait_for_stop_event (SBProcess process, SBListener listener)<br>
+{<br>
+    bool stopped = false;<br>
+    while (!stopped)<br>
+    {<br>
+        SBEvent event;<br>
+        bool waitfor_ret = listener.WaitForEvent (2, event);<br>
+        if (event.GetType() == SBProcess::eBroadcastBitStateChanged)<br>
+        {<br>
+            if (process.GetState() == StateType::eStateStopped<br>
+                || process.GetState() == StateType::eStateCrashed<br>
+                || process.GetState() == StateType::eStateDetached<br>
+                || process.GetState() == StateType::eStateExited)<br>
+            {<br>
+                stopped = true;<br>
+            }<br>
+        }<br>
+    }<br>
+    return stopped;<br>
+}<br>
+<br>
+bool<br>
+walk_stack_to_main (SBThread thread)<br>
+{<br>
+    if (thread.IsValid() == 0)<br>
+    {<br>
+        return false;<br>
+    }<br>
+<br>
+    bool found_main = false;<br>
+    uint32_t curr_frame = 0;<br>
+    const uint32_t framecount = thread.GetNumFrames();<br>
+    while (!found_main && curr_frame < framecount)<br>
+    {<br>
+        SBFrame frame = thread.GetFrameAtIndex (curr_frame);<br>
+        if (strcmp (frame.GetFunctionName(), "main") == 0)<br>
+        {<br>
+            found_main = true;<br>
+            break;<br>
+        }<br>
+        curr_frame += 1;<br>
+    }<br>
+    return found_main;<br>
+}<br>
+<br>
+void *do_one_debugger (void *in)<br>
+{<br>
+    uint64_t threadnum = (uint64_t) in;<br>
+<br>
+#if defined (__APPLE__)<br>
+    char *threadname;<br>
+    asprintf (&threadname, "thread #%lld", threadnum);<br>
+    pthread_setname_np (threadname);<br>
+    free (threadname);<br>
+#endif<br>
+<br>
+#if DEBUG == 1<br>
+    printf ("#%lld: Starting debug session\n", threadnum);<br>
+#endif<br>
+<br>
+    SBDebugger debugger = lldb::SBDebugger::Create (false);<br>
+    if (debugger.IsValid ())<br>
+    {<br>
+        debugger.SetAsync (true);<br>
+        SBTarget target = debugger.CreateTargetWithFileAndArch("testprog", "x86_64");<br>
+        SBCommandInterpreter command_interp = debugger.GetCommandInterpreter();<br>
+        if (target.IsValid())<br>
+        {<br>
+            SBBreakpoint bar_br = target.BreakpointCreateByName ("bar", "testprog");<br>
+            if (!bar_br.IsValid())<br>
+            {<br>
+                printf ("#%lld: failed to set breakpoint on bar, exiting.\n", threadnum);<br>
+                exit (1);<br>
+            }<br>
+            SBBreakpoint foo_br = target.BreakpointCreateByName ("foo", "testprog");<br>
+            if (!foo_br.IsValid())<br>
+            {<br>
+                printf ("#%lld: Failed to set breakpoint on foo()\n", threadnum);<br>
+            }<br>
+<br>
+            SBLaunchInfo launch_info (NULL);<br>
+            SBError error;<br>
+            SBProcess process = target.Launch (launch_info, error);<br>
+            if (process.IsValid())<br>
+            {<br>
+                SBListener listener = debugger.GetListener();<br>
+                SBBroadcaster broadcaster = process.GetBroadcaster();<br>
+                uint32_t rc = broadcaster.AddListener (listener, SBProcess::eBroadcastBitStateChanged);<br>
+                if (rc == 0)<br>
+                {<br>
+                    printf ("adding listener failed\n");<br>
+                    exit (1);<br>
+                }<br>
+<br>
+                wait_for_stop_event (process, listener);<br>
+<br>
+                if (!walk_stack_to_main (process.GetThreadAtIndex(0)))<br>
+                {<br>
+                    printf ("#%lld: backtrace while @ foo() failed\n", threadnum);<br>
+                    completed_threads_array[threadnum] = true;<br>
+                    return (void *) 1;<br>
+                }<br>
+<br>
+                if (strcmp (process.GetThreadAtIndex(0).GetFrameAtIndex(0).GetFunctionName(), "foo") != 0)<br>
+                {<br>
+#if DEBUG == 1<br>
+                    printf ("#%lld: First breakpoint did not stop at foo(), instead stopped at '%s'\n", threadnum, process.GetThreadAtIndex(0).GetFrameAtIndex(0).GetFunctionName());<br>
+#endif<br>
+                    completed_threads_array[threadnum] = true;<br>
+                    return (void*) 1;<br>
+                }<br>
+<br>
+                process.Continue();<br>
+<br>
+                wait_for_stop_event (process, listener);<br>
+<br>
+                if (process.GetState() == StateType::eStateExited)<br>
+                {<br>
+                    printf ("#%lld: Process exited\n", threadnum);<br>
+                    completed_threads_array[threadnum] = true;<br>
+                    return (void *) 1;<br>
+                }<br>
+<br>
+<br>
+                if (!walk_stack_to_main (process.GetThreadAtIndex(0)))<br>
+                {<br>
+                    printf ("#%lld: backtrace while @ bar() failed\n", threadnum);<br>
+                    completed_threads_array[threadnum] = true;<br>
+                    return (void *) 1;<br>
+                }<br>
+<br>
+                if (strcmp (process.GetThreadAtIndex(0).GetFrameAtIndex(0).GetFunctionName(), "bar") != 0)<br>
+                {<br>
+                    printf ("#%lld: First breakpoint did not stop at bar()\n", threadnum);<br>
+                    completed_threads_array[threadnum] = true;<br>
+                    return (void*) 1;<br>
+                }<br>
+<br>
+                process.Kill();<br>
+<br>
+                wait_for_stop_event (process, listener);<br>
+<br>
+                SBDebugger::Destroy(debugger);<br>
+<br>
+#if DEBUG == 1<br>
+                printf ("#%lld: All good!\n", threadnum);<br>
+#endif<br>
+                successful_threads_array[threadnum] = true;<br>
+                completed_threads_array[threadnum] = true;<br>
+                return (void*) 0;<br>
+            }<br>
+            else<br>
+            {<br>
+                printf("#%lld: process failed to launch\n", threadnum);<br>
+                successful_threads_array[threadnum] = false;<br>
+                completed_threads_array[threadnum] = true;<br>
+                return (void*) 0;<br>
+            }<br>
+        }<br>
+        else<br>
+        {<br>
+            printf ("#%lld: did not get valid target\n", threadnum);<br>
+            successful_threads_array[threadnum] = false;<br>
+            completed_threads_array[threadnum] = true;<br>
+            return (void*) 0;<br>
+        }<br>
+    }<br>
+    else<br>
+    {<br>
+        printf ("#%lld: did not get debugger\n", threadnum);<br>
+        successful_threads_array[threadnum] = false;<br>
+        completed_threads_array[threadnum] = true;<br>
+        return (void*) 0;<br>
+    }<br>
+    completed_threads_array[threadnum] = true;<br>
+    return (void*) 1;<br>
+}<br>
+<br>
+int main ()<br>
+{<br>
+    SBDebugger::Initialize();<br>
+<br>
+    completed_threads_array = (bool *) malloc (sizeof (bool) * NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);<br>
+    memset (completed_threads_array, 0, sizeof (bool) * NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);<br>
+    successful_threads_array = (bool *) malloc (sizeof (bool) * NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);<br>
+    memset (successful_threads_array, 0, sizeof (bool) * NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);<br>
+<br>
+    for (uint64_t i = 0; i< NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS; i++)<br>
+    {<br>
+        pthread_t thread;<br>
+        pthread_create (&thread, NULL, do_one_debugger, (void*) i);<br>
+    }<br>
+<br>
+<br>
+    int max_time_to_wait = 20;  // 20 iterations, or 60 seconds<br>
+    int iter = 0;<br>
+    while (1)<br>
+    {<br>
+        sleep (3);<br>
+        bool all_done = true;<br>
+        int successful_threads = 0;<br>
+        int total_completed_threads = 0;<br>
+        for (uint64_t i = 0; i < NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS; i++)<br>
+        {<br>
+            if (successful_threads_array[i] == true)<br>
+                successful_threads++;<br>
+            if (completed_threads_array[i] == true)<br>
+                total_completed_threads++;<br>
+            if (completed_threads_array[i] == false)<br>
+            {<br>
+                all_done = false;<br>
+            }<br>
+        }<br>
+        if (all_done)<br>
+        {<br>
+#if DEBUG == 1<br>
+            printf ("All threads completed.\n");<br>
+            printf ("%d threads completed successfully out of %d\n", successful_threads, NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);<br>
+#endif<br>
+            SBDebugger::Terminate();<br>
+            exit(0);<br>
+        }<br>
+        else<br>
+        {<br>
+#if DEBUG == 1<br>
+            printf ("%d threads completed so far (%d successfully), out of %d\n", total_completed_threads, successful_threads, NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);<br>
+#endif<br>
+        }<br>
+        if (iter++ == max_time_to_wait)<br>
+        {<br>
+            printf ("reached maximum timeout but only %d threads have completed so far (%d successfully), out of %d.  Exiting.\n", total_completed_threads, successful_threads, NUMBER_OF_SIMULTANEOUS_DEBUG_SESSIONS);<br>

+            break;<br>
+        }<br>
+    }<br>
+<br>
+<br>
+    SBDebugger::Terminate();<br>
+    exit (1);<br>
+}<br>
<br>
Added: lldb/trunk/test/api/multiple-debuggers/testprog.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/test/api/multiple-debuggers/testprog.cpp?rev=212671&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/test/api/multiple-debuggers/testprog.cpp?rev=212671&view=auto</a><br>

==============================================================================<br>
--- lldb/trunk/test/api/multiple-debuggers/testprog.cpp (added)<br>
+++ lldb/trunk/test/api/multiple-debuggers/testprog.cpp Wed Jul  9 21:17:31 2014<br>
@@ -0,0 +1,12 @@<br>
+int bar ()<br>
+{<br>
+    return 5;<br>
+}<br>
+int foo ()<br>
+{<br>
+    return bar() + 5;<br>
+}<br>
+int main ()<br>
+{<br>
+    return foo();<br>
+}<br>
<br>
<br>
_______________________________________________<br>
lldb-commits mailing list<br>
<a href="mailto:lldb-commits@cs.uiuc.edu">lldb-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits</a><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div dir="ltr"><table cellspacing="0" cellpadding="0" style="color:rgb(136,136,136);font-family:'Times New Roman'"><tbody><tr style="color:rgb(85,85,85);font-family:sans-serif;font-size:small">
<td nowrap style="border-top-style:solid;border-top-color:rgb(213,15,37);border-top-width:2px">Todd Fiala |</td><td nowrap style="border-top-style:solid;border-top-color:rgb(51,105,232);border-top-width:2px"> Software Engineer |</td>
<td nowrap style="border-top-style:solid;border-top-color:rgb(0,153,57);border-top-width:2px"> <a href="mailto:tfiala@google.com" style="color:rgb(17,85,204)" target="_blank"><span style="background-color:rgb(255,255,204);color:rgb(34,34,34);background-repeat:initial initial">tfiala@google.com</span></a> |</td>
<td nowrap style="border-top-style:solid;border-top-color:rgb(238,178,17);border-top-width:2px"><font color="#1155cc"> <a>650-943-3180</a></font></td></tr></tbody></table><br></div>
</div>