[Lldb-commits] [lldb] r237392 - Enable multithreaded debugging on Windows.

Vince Harron vince at nethacker.com
Thu May 14 18:25:42 PDT 2015


There is a new test failure in Linux after this change.  Can we revert to
green and help you figure it out?

======================================================================
FAIL: test_with_dwarf (TestNumThreads.NumberOfThreadsTestCase)
   Test number of threads.
----------------------------------------------------------------------
Traceback (most recent call last):
  File
"/usr/local/google/home/vharron/bisect/tmp/llvm/tools/lldb/test/lldbtest.py",
line 499, in wrapper
    return func(self, *args, **kwargs)
  File
"/usr/local/google/home/vharron/bisect/tmp/llvm/tools/lldb/test/functionalities/thread/TestNumThreads.py",
line 26, in test_with_dwarf
    self.number_of_threads_test()
  File
"/usr/local/google/home/vharron/bisect/tmp/llvm/tools/lldb/test/functionalities/thread/TestNumThreads.py",
line 51, in number_of_threads_test
    substrs = ["stop reason = breakpoint 1."])
  File
"/usr/local/google/home/vharron/bisect/tmp/llvm/tools/lldb/test/lldbtest.py",
line 2344, in expect
    msg if msg else EXP_MSG(str, exe))
AssertionError: False is not True : Process should be stopped due to
breakpoint
Config=i386-gcc
----------------------------------------------------------------------




On Thu, May 14, 2015 at 2:07 PM, Adrian McCarthy <amccarth at google.com>
wrote:

> Author: amccarth
> Date: Thu May 14 16:07:59 2015
> New Revision: 237392
>
> URL: http://llvm.org/viewvc/llvm-project?rev=237392&view=rev
> Log:
> Enable multithreaded debugging on Windows.
>
> Added:
>     lldb/trunk/test/functionalities/thread/main.cpp
> Removed:
>     lldb/trunk/test/functionalities/thread/main.c
> Modified:
>     lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.cpp
>     lldb/trunk/source/Plugins/Process/Windows/ExceptionRecord.h
>     lldb/trunk/source/Plugins/Process/Windows/IDebugDelegate.h
>     lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.cpp
>     lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.h
>     lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp
>     lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.h
>     lldb/trunk/source/Target/ThreadList.cpp
>     lldb/trunk/test/functionalities/thread/Makefile
>     lldb/trunk/test/functionalities/thread/TestNumThreads.py
>
> Modified: lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.cpp?rev=237392&r1=237391&r2=237392&view=diff
>
> ==============================================================================
> --- lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.cpp (original)
> +++ lldb/trunk/source/Plugins/Process/Windows/DebuggerThread.cpp Thu May
> 14 16:07:59 2015
> @@ -283,9 +283,9 @@ DebuggerThread::HandleExceptionEvent(con
>  {
>      bool first_chance = (info.dwFirstChance != 0);
>
> -    m_active_exception.reset(new ExceptionRecord(info.ExceptionRecord));
> +    m_active_exception.reset(new ExceptionRecord(info.ExceptionRecord,
> thread_id));
>      WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION,
> -                 "HandleExceptionEvent encountered %s chance exception
> 0x%x on thread %u",
> +                 "HandleExceptionEvent encountered %s chance exception
> 0x%x on thread 0x%x",
>                   first_chance ? "first" : "second",
> info.ExceptionRecord.ExceptionCode, thread_id);
>
>      ExceptionResult result =
> m_debug_delegate->OnDebugException(first_chance,
> @@ -308,9 +308,11 @@ DWORD
>  DebuggerThread::HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO
> &info, DWORD thread_id)
>  {
>      WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_THREAD,
> -        "HandleCreateThreadEvent Thread %u spawned in process %I64u",
> -        m_process.GetProcessId(), thread_id);
> -
> +        "HandleCreateThreadEvent Thread 0x%x spawned in process %I64u",
> +        thread_id, m_process.GetProcessId());
> +    HostThread thread(info.hThread);
> +    thread.GetNativeThread().SetOwnsHandle(false);
> +    m_debug_delegate->OnCreateThread(thread);
>      return DBG_CONTINUE;
>  }
>
> @@ -347,7 +349,7 @@ DebuggerThread::HandleExitThreadEvent(co
>      WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_THREAD,
>          "HandleExitThreadEvent Thread %u exited with code %u in process
> %I64u",
>          thread_id, info.dwExitCode, m_process.GetProcessId());
> -
> +    m_debug_delegate->OnExitThread(thread_id, info.dwExitCode);
>      return DBG_CONTINUE;
>  }
>
> @@ -358,9 +360,9 @@ DebuggerThread::HandleExitProcessEvent(c
>          "HandleExitProcessEvent process %I64u exited with code %u",
>          m_process.GetProcessId(), info.dwExitCode);
>
> -    FreeProcessHandles();
> -
>      m_debug_delegate->OnExitProcess(info.dwExitCode);
> +
> +    FreeProcessHandles();
>      return DBG_CONTINUE;
>  }
>
>
> Modified: lldb/trunk/source/Plugins/Process/Windows/ExceptionRecord.h
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/ExceptionRecord.h?rev=237392&r1=237391&r2=237392&view=diff
>
> ==============================================================================
> --- lldb/trunk/source/Plugins/Process/Windows/ExceptionRecord.h (original)
> +++ lldb/trunk/source/Plugins/Process/Windows/ExceptionRecord.h Thu May 14
> 16:07:59 2015
> @@ -30,13 +30,14 @@ namespace lldb_private
>  class ExceptionRecord
>  {
>    public:
> -    explicit ExceptionRecord(const EXCEPTION_RECORD &record)
> +    ExceptionRecord(const EXCEPTION_RECORD &record, lldb::tid_t thread_id)
>      {
>          m_code = record.ExceptionCode;
>          m_continuable = (record.ExceptionFlags == 0);
>          if (record.ExceptionRecord)
> -            m_next_exception.reset(new
> ExceptionRecord(*record.ExceptionRecord));
> +            m_next_exception.reset(new
> ExceptionRecord(*record.ExceptionRecord, thread_id));
>          m_exception_addr =
> reinterpret_cast<lldb::addr_t>(record.ExceptionAddress);
> +        m_thread_id = thread_id;
>          m_arguments.assign(record.ExceptionInformation,
> record.ExceptionInformation + record.NumberParameters);
>      }
>      virtual ~ExceptionRecord() {}
> @@ -62,11 +63,18 @@ class ExceptionRecord
>          return m_exception_addr;
>      }
>
> +    lldb::tid_t
> +    GetThreadID() const
> +    {
> +        return m_thread_id;
> +    }
> +
>    private:
>      DWORD m_code;
>      bool m_continuable;
>      std::shared_ptr<ExceptionRecord> m_next_exception;
>      lldb::addr_t m_exception_addr;
> +    lldb::tid_t m_thread_id;
>      std::vector<ULONG_PTR> m_arguments;
>  };
>  }
>
> Modified: lldb/trunk/source/Plugins/Process/Windows/IDebugDelegate.h
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/IDebugDelegate.h?rev=237392&r1=237391&r2=237392&view=diff
>
> ==============================================================================
> --- lldb/trunk/source/Plugins/Process/Windows/IDebugDelegate.h (original)
> +++ lldb/trunk/source/Plugins/Process/Windows/IDebugDelegate.h Thu May 14
> 16:07:59 2015
> @@ -35,7 +35,7 @@ class IDebugDelegate
>      virtual void OnDebuggerConnected(lldb::addr_t image_base) = 0;
>      virtual ExceptionResult OnDebugException(bool first_chance, const
> ExceptionRecord &record) = 0;
>      virtual void OnCreateThread(const HostThread &thread) = 0;
> -    virtual void OnExitThread(const HostThread &thread) = 0;
> +    virtual void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code)
> = 0;
>      virtual void OnLoadDll(const ModuleSpec &module_spec, lldb::addr_t
> module_addr) = 0;
>      virtual void OnUnloadDll(lldb::addr_t module_addr) = 0;
>      virtual void OnDebugString(const std::string &string) = 0;
>
> Modified: lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.cpp?rev=237392&r1=237391&r2=237392&view=diff
>
> ==============================================================================
> --- lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.cpp
> (original)
> +++ lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.cpp Thu
> May 14 16:07:59 2015
> @@ -43,9 +43,9 @@ LocalDebugDelegate::OnCreateThread(const
>  }
>
>  void
> -LocalDebugDelegate::OnExitThread(const HostThread &thread)
> +LocalDebugDelegate::OnExitThread(lldb::tid_t thread_id, uint32_t
> exit_code)
>  {
> -    ((ProcessWindows &)*m_process).OnExitThread(thread);
> +    ((ProcessWindows &)*m_process).OnExitThread(thread_id, exit_code);
>  }
>
>  void
>
> Modified: lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.h
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.h?rev=237392&r1=237391&r2=237392&view=diff
>
> ==============================================================================
> --- lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.h
> (original)
> +++ lldb/trunk/source/Plugins/Process/Windows/LocalDebugDelegate.h Thu May
> 14 16:07:59 2015
> @@ -46,7 +46,7 @@ class LocalDebugDelegate : public IDebug
>      void OnDebuggerConnected(lldb::addr_t image_base) override;
>      ExceptionResult OnDebugException(bool first_chance, const
> ExceptionRecord &record) override;
>      void OnCreateThread(const HostThread &thread) override;
> -    void OnExitThread(const HostThread &thread) override;
> +    void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) override;
>      void OnLoadDll(const lldb_private::ModuleSpec &module_spec,
> lldb::addr_t module_addr) override;
>      void OnUnloadDll(lldb::addr_t module_addr) override;
>      void OnDebugString(const std::string &message) override;
>
> Modified: lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp?rev=237392&r1=237391&r2=237392&view=diff
>
> ==============================================================================
> --- lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp (original)
> +++ lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.cpp Thu May
> 14 16:07:59 2015
> @@ -13,6 +13,7 @@
>  // C++ Includes
>  #include <list>
>  #include <mutex>
> +#include <set>
>  #include <vector>
>
>  // Other libraries and framework includes
> @@ -78,7 +79,7 @@ class ProcessWindowsData
>      HANDLE m_initial_stop_event;
>      bool m_initial_stop_received;
>      std::map<lldb::tid_t, HostThread> m_new_threads;
> -    std::map<lldb::tid_t, HostThread> m_exited_threads;
> +    std::set<lldb::tid_t> m_exited_threads;
>  };
>  }
>
>  //------------------------------------------------------------------------------
> @@ -425,11 +426,11 @@ ProcessWindows::RefreshStateAfterStop()
>      }
>
>      StopInfoSP stop_info;
> +    m_thread_list.SetSelectedThreadByID(active_exception->GetThreadID());
>      ThreadSP stop_thread = m_thread_list.GetSelectedThread();
>      RegisterContextSP register_context =
> stop_thread->GetRegisterContext();
>
>      // The current EIP is AFTER the BP opcode, which is one byte.
> -    // TODO(zturner): Can't we just use
> active_exception->GetExceptionAddress()?
>      uint64_t pc = register_context->GetPC() - 1;
>      if (active_exception->GetExceptionCode() == EXCEPTION_BREAKPOINT)
>      {
> @@ -445,7 +446,8 @@ ProcessWindows::RefreshStateAfterStop()
>              if (site->ValidForThisThread(stop_thread.get()))
>              {
>                  WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS |
> WINDOWS_LOG_EXCEPTION,
> -                             "Breakpoint site %d is valid for this
> thread, creating stop info.", site->GetID());
> +                             "Breakpoint site %d is valid for this thread
> (0x%I64x), creating stop info.",
> +                             site->GetID(), stop_thread->GetID());
>
>                  stop_info =
> StopInfo::CreateStopReasonWithBreakpointSiteID(
>                      *stop_thread, site->GetID());
> @@ -471,8 +473,8 @@ ProcessWindows::RefreshStateAfterStop()
>      {
>          std::string desc;
>          llvm::raw_string_ostream desc_stream(desc);
> -        desc_stream << "Exception 0x" <<
> llvm::format_hex(active_exception->GetExceptionCode(), 8)
> -                    << " encountered at address 0x" <<
> llvm::format_hex(pc, 8);
> +        desc_stream << "Exception " <<
> llvm::format_hex(active_exception->GetExceptionCode(), 8)
> +                    << " encountered at address " << llvm::format_hex(pc,
> 8);
>          stop_info = StopInfo::CreateStopReasonWithException(*stop_thread,
> desc_stream.str().c_str());
>          stop_thread->SetStopInfo(stop_info);
>          WINLOG_IFALL(WINDOWS_LOG_EXCEPTION, desc_stream.str().c_str());
> @@ -701,7 +703,7 @@ ProcessWindows::OnDebugException(bool fi
>      if (!m_session_data)
>      {
>          WINERR_IFANY(WINDOWS_LOG_EXCEPTION,
> -                     "Debugger thread reported exception 0x%u at address
> 0x%I64x, but there is no session.",
> +                     "Debugger thread reported exception 0x%x at address
> 0x%I64x, but there is no session.",
>                       record.GetExceptionCode(),
> record.GetExceptionAddress());
>          return ExceptionResult::SendToApplication;
>      }
> @@ -732,7 +734,7 @@ ProcessWindows::OnDebugException(bool fi
>              break;
>          default:
>              WINLOG_IFANY(WINDOWS_LOG_EXCEPTION,
> -                         "Debugger thread reported exception 0x%u at
> address 0x%I64x (first_chance=%s)",
> +                         "Debugger thread reported exception 0x%x at
> address 0x%I64x (first_chance=%s)",
>                           record.GetExceptionCode(),
> record.GetExceptionAddress(), BOOL_STR(first_chance));
>              // For non-breakpoints, give the application a chance to
> handle the exception first.
>              if (first_chance)
> @@ -753,18 +755,22 @@ ProcessWindows::OnCreateThread(const Hos
>  }
>
>  void
> -ProcessWindows::OnExitThread(const HostThread &exited_thread)
> +ProcessWindows::OnExitThread(lldb::tid_t thread_id, uint32_t exit_code)
>  {
>      llvm::sys::ScopedLock lock(m_mutex);
>
> +    // On a forced termination, we may get exit thread events after the
> session
> +    // data has been cleaned up.
> +    if (!m_session_data)
> +        return;
> +
>      // A thread may have started and exited before the debugger stopped
> allowing a refresh.
>      // Just remove it from the new threads list in that case.
> -    const HostThreadWindows &wexited_thread =
> exited_thread.GetNativeThread();
> -    auto iter =
> m_session_data->m_new_threads.find(wexited_thread.GetThreadId());
> +    auto iter = m_session_data->m_new_threads.find(thread_id);
>      if (iter != m_session_data->m_new_threads.end())
>          m_session_data->m_new_threads.erase(iter);
>      else
> -        m_session_data->m_exited_threads[wexited_thread.GetThreadId()] =
> exited_thread;
> +        m_session_data->m_exited_threads.insert(thread_id);
>  }
>
>  void
>
> Modified: lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.h
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.h?rev=237392&r1=237391&r2=237392&view=diff
>
> ==============================================================================
> --- lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.h (original)
> +++ lldb/trunk/source/Plugins/Process/Windows/ProcessWindows.h Thu May 14
> 16:07:59 2015
> @@ -109,7 +109,7 @@ public:
>      void OnDebuggerConnected(lldb::addr_t image_base) override;
>      ExceptionResult OnDebugException(bool first_chance, const
> lldb_private::ExceptionRecord &record) override;
>      void OnCreateThread(const lldb_private::HostThread &thread) override;
> -    void OnExitThread(const lldb_private::HostThread &thread) override;
> +    void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) override;
>      void OnLoadDll(const lldb_private::ModuleSpec &module_spec,
> lldb::addr_t module_addr) override;
>      void OnUnloadDll(lldb::addr_t module_addr) override;
>      void OnDebugString(const std::string &string) override;
>
> Modified: lldb/trunk/source/Target/ThreadList.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadList.cpp?rev=237392&r1=237391&r2=237392&view=diff
>
> ==============================================================================
> --- lldb/trunk/source/Target/ThreadList.cpp (original)
> +++ lldb/trunk/source/Target/ThreadList.cpp Thu May 14 16:07:59 2015
> @@ -247,8 +247,8 @@ ThreadList::ShouldStop (Event *event_ptr
>      // figuring out whether the thread plan conditions are met.  So we
> don't want
>      // to keep the ThreadList locked the whole time we are doing this.
>      // FIXME: It is possible that running code could cause new threads
> -    // to be created.  If that happens we will miss asking them whether
> -    // then should stop.  This is not a big deal, since we haven't had
> +    // to be created.  If that happens, we will miss asking them whether
> +    // they should stop.  This is not a big deal since we haven't had
>      // a chance to hang any interesting operations on those threads yet.
>
>      collection threads_copy;
>
> Modified: lldb/trunk/test/functionalities/thread/Makefile
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/thread/Makefile?rev=237392&r1=237391&r2=237392&view=diff
>
> ==============================================================================
> --- lldb/trunk/test/functionalities/thread/Makefile (original)
> +++ lldb/trunk/test/functionalities/thread/Makefile Thu May 14 16:07:59
> 2015
> @@ -1,5 +1,5 @@
>  LEVEL = ../../make
>
> -C_SOURCES := main.c
> +CXX_SOURCES := main.cpp
>  ENABLE_THREADS := YES
>  include $(LEVEL)/Makefile.rules
>
> Modified: lldb/trunk/test/functionalities/thread/TestNumThreads.py
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/thread/TestNumThreads.py?rev=237392&r1=237391&r2=237392&view=diff
>
> ==============================================================================
> --- lldb/trunk/test/functionalities/thread/TestNumThreads.py (original)
> +++ lldb/trunk/test/functionalities/thread/TestNumThreads.py Thu May 14
> 16:07:59 2015
> @@ -29,7 +29,7 @@ class NumberOfThreadsTestCase(TestBase):
>          # Call super's setUp().
>          TestBase.setUp(self)
>          # Find the line number to break inside main().
> -        self.line = line_number('main.c', '// Set break point at this
> line.')
> +        self.line = line_number('main.cpp', '// Set break point at this
> line.')
>
>      def number_of_threads_test(self):
>          """Test number of threads."""
> @@ -37,11 +37,11 @@ class NumberOfThreadsTestCase(TestBase):
>          self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
>
>          # This should create a breakpoint with 1 location.
> -        lldbutil.run_break_set_by_file_and_line (self, "main.c",
> self.line, num_expected_locations=1)
> +        lldbutil.run_break_set_by_file_and_line (self, "main.cpp",
> self.line, num_expected_locations=1)
>
>          # The breakpoint list should show 3 locations.
>          self.expect("breakpoint list -f", "Breakpoint location shown
> correctly",
> -            substrs = ["1: file = 'main.c', line = %d, locations = 1" %
> self.line])
> +            substrs = ["1: file = 'main.cpp', line = %d, locations = 1" %
> self.line])
>
>          # Run the program.
>          self.runCmd("run", RUN_SUCCEEDED)
> @@ -57,7 +57,9 @@ class NumberOfThreadsTestCase(TestBase):
>          # Get the number of threads
>          num_threads = process.GetNumThreads()
>
> -        self.assertTrue(num_threads == 4, 'Number of expected threads and
> actual threads do not match.')
> +        # Using std::thread may involve extra threads, so we assert that
> there are
> +        # at least 4 rather than exactly 4.
> +        self.assertTrue(num_threads >= 4, 'Number of expected threads and
> actual threads do not match.')
>
>  if __name__ == '__main__':
>      import atexit
>
> Removed: lldb/trunk/test/functionalities/thread/main.c
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/thread/main.c?rev=237391&view=auto
>
> ==============================================================================
> --- lldb/trunk/test/functionalities/thread/main.c (original)
> +++ lldb/trunk/test/functionalities/thread/main.c (removed)
> @@ -1,57 +0,0 @@
> -#include <pthread.h>
> -
> -pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
> -pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
> -
> -void *
> -thread3 (void *input)
> -{
> -    pthread_mutex_lock(&mutex);
> -    pthread_cond_signal(&cond); // Set break point at this line.
> -    pthread_mutex_unlock(&mutex);
> -    return NULL;
> -}
> -
> -void *
> -thread2 (void *input)
> -{
> -    pthread_mutex_lock(&mutex);
> -    pthread_cond_signal(&cond);
> -    pthread_cond_wait(&cond, &mutex);
> -    pthread_mutex_unlock(&mutex);
> -    return NULL;
> -}
> -
> -void *
> -thread1 (void *input)
> -{
> -    pthread_t thread_2;
> -    pthread_create (&thread_2, NULL, thread2, NULL);
> -
> -    pthread_join(thread_2, NULL);
> -
> -    return NULL;
> -}
> -
> -int main ()
> -{
> -    pthread_t thread_1;
> -    pthread_t thread_3;
> -
> -    pthread_mutex_lock (&mutex);
> -
> -    pthread_create (&thread_1, NULL, thread1, NULL);
> -
> -    pthread_cond_wait (&cond, &mutex);
> -
> -    pthread_create (&thread_3, NULL, thread3, NULL);
> -
> -    pthread_cond_wait (&cond, &mutex);
> -
> -    pthread_mutex_unlock (&mutex);
> -
> -    pthread_join (thread_1, NULL);
> -    pthread_join (thread_3, NULL);
> -
> -    return 0;
> -}
>
> Added: lldb/trunk/test/functionalities/thread/main.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/thread/main.cpp?rev=237392&view=auto
>
> ==============================================================================
> --- lldb/trunk/test/functionalities/thread/main.cpp (added)
> +++ lldb/trunk/test/functionalities/thread/main.cpp Thu May 14 16:07:59
> 2015
> @@ -0,0 +1,50 @@
> +#include <condition_variable>
> +#include <mutex>
> +#include <thread>
> +
> +std::mutex mutex;
> +std::condition_variable cond;
> +
> +void *
> +thread3(void *input)
> +{
> +    std::unique_lock<std::mutex> lock(mutex);
> +    cond.notify_all(); // Set break point at this line.
> +    return NULL;
> +}
> +
> +void *
> +thread2(void *input)
> +{
> +    std::unique_lock<std::mutex> lock(mutex);
> +    cond.notify_all();
> +    cond.wait(lock);
> +    return NULL;
> +}
> +
> +void *
> +thread1(void *input)
> +{
> +    std::thread thread_2(thread2, nullptr);
> +    thread_2.join();
> +
> +    return NULL;
> +}
> +
> +int main()
> +{
> +    std::unique_lock<std::mutex> lock(mutex);
> +
> +    std::thread thread_1(thread1, nullptr);
> +    cond.wait(lock);
> +
> +    std::thread thread_3(thread3, nullptr);
> +    cond.wait(lock);
> +
> +    lock.unlock();
> +
> +    thread_1.join();
> +    thread_3.join();
> +
> +    return 0;
> +}
>
>
> _______________________________________________
> lldb-commits mailing list
> lldb-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-commits/attachments/20150514/8eb25d17/attachment.html>


More information about the lldb-commits mailing list