Refactored the code to spawn a single driver thread on startup, and then spawn 
slave threads for each debugee.

http://reviews.llvm.org/D6037

Files:
  include/lldb/Host/Predicate.h
  include/lldb/Host/ProcessStatusMonitor.h
  include/lldb/Host/windows/HostThreadWindows.h
  source/Plugins/Process/Windows/CMakeLists.txt
  source/Plugins/Process/Windows/DebugDriverThread.cpp
  source/Plugins/Process/Windows/DebugDriverThread.h
  source/Plugins/Process/Windows/DebugMonitorMessageResults.cpp
  source/Plugins/Process/Windows/DebugMonitorMessageResults.h
  source/Plugins/Process/Windows/DebugMonitorMessages.cpp
  source/Plugins/Process/Windows/DebugMonitorMessages.h
  source/Plugins/Process/Windows/DebugOneProcessThread.cpp
  source/Plugins/Process/Windows/DebugOneProcessThread.h
  source/Plugins/Process/Windows/DebugProcessLauncher.cpp
  source/Plugins/Process/Windows/DebugProcessLauncher.h
  source/Plugins/Process/Windows/ProcessWindows.cpp
  source/Plugins/Process/Windows/ProcessWindows.h
  source/Plugins/Process/Windows/SlaveMessages.h
Index: include/lldb/Host/Predicate.h
===================================================================
--- include/lldb/Host/Predicate.h
+++ include/lldb/Host/Predicate.h
@@ -11,6 +11,7 @@
 #define liblldb_Predicate_h_
 #if defined(__cplusplus)
 
+#include "lldb/lldb-defines.h"
 #include "lldb/Host/Mutex.h"
 #include "lldb/Host/Condition.h"
 #include <stdint.h>
Index: include/lldb/Host/ProcessStatusMonitor.h
===================================================================
--- include/lldb/Host/ProcessStatusMonitor.h
+++ include/lldb/Host/ProcessStatusMonitor.h
@@ -26,7 +26,8 @@
 struct ProcessStatusMonitorCallbackEntry
 {
     ProcessStatusMonitorCallbackEntry(ProcessStatusMonitorCallback callback, void *baton)
-        : m_callback(callback), m_baton(baton)
+        : m_callback(callback)
+        , m_baton(baton)
     {
     }
     ProcessStatusMonitorCallback m_callback;
Index: include/lldb/Host/windows/HostThreadWindows.h
===================================================================
--- include/lldb/Host/windows/HostThreadWindows.h
+++ include/lldb/Host/windows/HostThreadWindows.h
@@ -31,9 +31,6 @@
     virtual void Reset();
 
     lldb::tid_t GetThreadId() const;
-
-  protected:
-    llvm::SmallString<32> m_thread_name;
 };
 }
 
Index: source/Plugins/Process/Windows/CMakeLists.txt
===================================================================
--- source/Plugins/Process/Windows/CMakeLists.txt
+++ source/Plugins/Process/Windows/CMakeLists.txt
@@ -4,6 +4,11 @@
 include_directories(../Utility)
 
 add_lldb_library(lldbPluginProcessWindows
+  DebugMonitorMessages.cpp
+  DebugMonitorMessageResults.cpp
+  DebugOneProcessThread.cpp
+  DebugProcessLauncher.cpp
+  DebugDriverThread.cpp
   ProcessWindows.cpp
   )
 
Index: source/Plugins/Process/Windows/DebugDriverThread.cpp
===================================================================
--- /dev/null
+++ source/Plugins/Process/Windows/DebugDriverThread.cpp
@@ -0,0 +1,247 @@
+//===-- DebugDriverThread.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DebugDriverThread.h"
+#include "DebugMonitorMessages.h"
+#include "DebugMonitorMessageResults.h"
+#include "DebugOneProcessThread.h"
+#include "SlaveMessages.h"
+
+#include "lldb/Core/Log.h"
+#include "lldb/Host/ThreadLauncher.h"
+#include "lldb/Target/Process.h"
+
+#include <vector>
+
+using namespace lldb;
+using namespace lldb_private;
+
+DebugDriverThread *DebugDriverThread::m_instance = NULL;
+
+DebugDriverThread::DebugDriverThread()
+{
+    m_monitor_thread = ThreadLauncher::LaunchThread("lldb.plugin.process-windows.monitor-thread", MonitorThread, this, nullptr);
+    m_shutdown_event = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+    m_monitor_event = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+    ::CreatePipe(&m_monitor_pipe_read, &m_monitor_pipe_write, NULL, 1024);
+}
+
+DebugDriverThread::~DebugDriverThread()
+{
+}
+
+void
+DebugDriverThread::Initialize()
+{
+    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
+    if (log)
+        log->Printf("DebugDriverThread::Initialize");
+
+    m_instance = new DebugDriverThread();
+}
+
+void
+DebugDriverThread::Teardown()
+{
+    m_instance->Shutdown();
+
+    delete m_instance;
+    m_instance = nullptr;
+}
+
+void
+DebugDriverThread::Shutdown()
+{
+    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
+    if (log)
+        log->Printf("DebugDriverThread::Shutdown");
+
+    if (!m_shutdown_event)
+        return;
+    ::SetEvent(m_shutdown_event);
+    m_monitor_thread.Join(nullptr);
+
+    ::CloseHandle(m_shutdown_event);
+    ::CloseHandle(m_monitor_event);
+    ::CloseHandle(m_monitor_pipe_read);
+    ::CloseHandle(m_monitor_pipe_write);
+
+    m_shutdown_event = nullptr;
+    m_monitor_event = nullptr;
+    m_monitor_pipe_read = nullptr;
+    m_monitor_pipe_write = nullptr;
+}
+
+DebugDriverThread &
+DebugDriverThread::GetInstance()
+{
+    return *m_instance;
+}
+
+void
+DebugDriverThread::PostDebugMessage(const DebugMonitorMessage *message)
+{
+    message->Retain();
+    if (!::WriteFile(m_monitor_pipe_write, &message, sizeof(message), NULL, NULL))
+    {
+        message->Release();
+        return;
+    }
+
+    ::SetEvent(m_monitor_event);
+}
+
+const DebugMonitorMessageResult *
+DebugDriverThread::HandleMonitorMessage(const DebugMonitorMessage *message)
+{
+    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+    switch (message->GetMessageType())
+    {
+        case MonitorMessageType::eLaunchProcess:
+        {
+            const auto *launch_message = static_cast<const LaunchProcessMessage *>(message);
+            return HandleMonitorMessage(launch_message);
+        }
+        default:
+            if (log)
+                log->Printf("DebugDriverThread received unknown message type %d.", message->GetMessageType());
+            return nullptr;
+    }
+}
+
+const LaunchProcessMessageResult *
+DebugDriverThread::HandleMonitorMessage(const LaunchProcessMessage *launch_message)
+{
+    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+    const char *exe = launch_message->GetLaunchInfo().GetExecutableFile().GetPath().c_str();
+    if (log)
+        log->Printf("DebugDriverThread launching process '%s'.", exe);
+
+    // Create a DebugOneProcessThread which will do the actual creation and enter a debug loop on
+    // a background thread, only returning after the process has been created on the background
+    // thread.
+    std::shared_ptr<DebugOneProcessThread> slave(new DebugOneProcessThread(m_monitor_thread));
+    const LaunchProcessMessageResult *result = slave->DebugLaunch(launch_message);
+    if (result && result->GetError().Success())
+    {
+        if (log)
+            log->Printf("DebugDriverThread launched process '%s' with PID %d.", exe, result->GetProcess().GetProcessId());
+        m_debugged_processes.insert(std::make_pair(result->GetProcess().GetProcessId(), slave));
+    }
+    else
+    {
+        if (log)
+            log->Printf("An error occured launching process '%s' -- %s.", exe, result->GetError().AsCString());
+    }
+    return result;
+}
+
+void
+DebugDriverThread::HandleSlaveEvent(const SlaveMessageProcessExited &message)
+{
+    lldb::pid_t pid = message.GetProcess().GetProcessId();
+
+    m_debugged_processes.erase(pid);
+
+    Process::SetProcessExitStatus(nullptr, pid, true, 0, message.GetExitCode());
+}
+
+void
+DebugDriverThread::HandleSlaveEvent(const SlaveMessageRipEvent &message)
+{
+    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+    lldb::pid_t pid = message.GetProcess().GetProcessId();
+    m_debugged_processes.erase(pid);
+
+    if (log)
+    {
+        log->Printf("An error was encountered while debugging process %d.  Debugging has been terminated.  Error = s.", pid,
+                    message.GetError().AsCString());
+    }
+}
+
+bool
+DebugDriverThread::ProcessMonitorMessages()
+{
+    DWORD bytes_available = 0;
+    if (!PeekNamedPipe(m_monitor_pipe_read, NULL, 0, NULL, &bytes_available, NULL))
+    {
+        // There's some kind of error with the named pipe.  Fail out and stop monitoring.
+        return false;
+    }
+
+    if (bytes_available <= 0)
+    {
+        // There's no data available, but the operation succeeded.
+        return true;
+    }
+
+    int count = bytes_available / sizeof(DebugMonitorMessage *);
+    std::vector<DebugMonitorMessage *> messages(count);
+    if (!::ReadFile(m_monitor_pipe_read, &messages[0], bytes_available, NULL, NULL))
+        return false;
+
+    for (DebugMonitorMessage *message : messages)
+    {
+        const DebugMonitorMessageResult *result = HandleMonitorMessage(message);
+        message->CompleteMessage(result);
+        message->Release();
+    }
+    return true;
+}
+
+lldb::thread_result_t
+DebugDriverThread::MonitorThread(void *data)
+{
+    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+    if (log)
+        log->Printf("ProcessWindows DebugDriverThread starting up.");
+
+    DebugDriverThread *monitor_thread = static_cast<DebugDriverThread *>(data);
+    const int kMonitorEventIndex = 0;
+    const int kShutdownEventIndex = 1;
+
+    Error error;
+    HANDLE events[kShutdownEventIndex + 1];
+    events[kMonitorEventIndex] = monitor_thread->m_monitor_event;
+    events[kShutdownEventIndex] = monitor_thread->m_shutdown_event;
+
+    while (true)
+    {
+        bool exit = false;
+        // See if any new processes are ready for debug monitoring.
+        DWORD result = WaitForMultipleObjectsEx(llvm::array_lengthof(events), events, FALSE, 1000, TRUE);
+        switch (result)
+        {
+            case WAIT_OBJECT_0 + kMonitorEventIndex:
+                // LLDB is telling us to do something.  Process pending messages in our queue.
+                monitor_thread->ProcessMonitorMessages();
+                break;
+            case WAIT_OBJECT_0 + kShutdownEventIndex:
+                error.SetErrorString("Shutdown event received.");
+                exit = true;
+                break;
+            case WAIT_TIMEOUT:
+            case WAIT_IO_COMPLETION:
+                break;
+            default:
+                error.SetError(GetLastError(), eErrorTypeWin32);
+                exit = true;
+                break;
+        }
+        if (exit)
+            break;
+    }
+
+    if (log)
+        log->Printf("ProcessWindows Debug monitor thread exiting.  %s", error.AsCString());
+    return 0;
+}
Index: source/Plugins/Process/Windows/DebugDriverThread.h
===================================================================
--- /dev/null
+++ source/Plugins/Process/Windows/DebugDriverThread.h
@@ -0,0 +1,80 @@
+//===-- DebugDriverThread.h -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Plugins_Process_Windows_DebugDriverThread_H_
+#define liblldb_Plugins_Process_Windows_DebugDriverThread_H_
+
+#include "lldb/Host/HostThread.h"
+#include "lldb/Host/ProcessStatusMonitor.h"
+#include "lldb/Host/windows/windows.h"
+#include "lldb/lldb-types.h"
+
+#include <map>
+
+class ProcessWindows;
+
+namespace lldb_private
+{
+class DebugMonitorMessage;
+class DebugMonitorMessageResult;
+class DebugOneProcessThread;
+class LaunchProcessMessage;
+class LaunchProcessMessageResult;
+
+class SlaveMessageProcessExited;
+class SlaveMessageRipEvent;
+
+//----------------------------------------------------------------------
+// DebugDriverThread
+//
+// Runs a background thread that pumps a queue from the application to tell the
+// debugger to do different things like launching processes, attaching to
+// processes, etc.
+//----------------------------------------------------------------------
+class DebugDriverThread
+{
+    friend class DebugOneProcessThread;
+
+  public:
+    virtual ~DebugDriverThread();
+
+    static void Initialize();
+    static void Teardown();
+    static DebugDriverThread &GetInstance();
+
+    void PostDebugMessage(const DebugMonitorMessage *message);
+
+  private:
+    DebugDriverThread();
+
+    void Shutdown();
+
+    bool ProcessMonitorMessages();
+    const DebugMonitorMessageResult *HandleMonitorMessage(const DebugMonitorMessage *message);
+    const LaunchProcessMessageResult *HandleMonitorMessage(const LaunchProcessMessage *launch_message);
+
+    // Slave message handlers.  These are invoked by the
+    void HandleSlaveEvent(const SlaveMessageProcessExited &message);
+    void HandleSlaveEvent(const SlaveMessageRipEvent &message);
+
+    static DebugDriverThread *m_instance;
+
+    std::map<lldb::pid_t, std::shared_ptr<DebugOneProcessThread>> m_debugged_processes;
+
+    HANDLE m_monitor_event;
+    HANDLE m_shutdown_event;
+    HANDLE m_monitor_pipe_read;
+    HANDLE m_monitor_pipe_write;
+    lldb_private::HostThread m_monitor_thread;
+
+    static lldb::thread_result_t MonitorThread(void *data);
+};
+}
+
+#endif
Index: source/Plugins/Process/Windows/DebugMonitorMessageResults.cpp
===================================================================
--- /dev/null
+++ source/Plugins/Process/Windows/DebugMonitorMessageResults.cpp
@@ -0,0 +1,55 @@
+//===-- DebugMonitorMessageResults.cpp --------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DebugMonitorMessageResults.h"
+#include "DebugMonitorMessages.h"
+
+#include "lldb/Core/Error.h"
+#include "lldb/Host/HostProcess.h"
+#include "lldb/Target/ProcessLaunchInfo.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+DebugMonitorMessageResult::DebugMonitorMessageResult(const DebugMonitorMessage *message)
+    : m_message(message)
+{
+    Retain();
+    if (m_message)
+        m_message->Retain();
+}
+
+DebugMonitorMessageResult::~DebugMonitorMessageResult()
+{
+    if (m_message)
+        m_message->Release();
+}
+
+void
+DebugMonitorMessageResult::SetError(const Error &error)
+{
+    m_error = error;
+}
+
+LaunchProcessMessageResult::LaunchProcessMessageResult(const LaunchProcessMessage *message)
+    : DebugMonitorMessageResult(message)
+{
+}
+
+LaunchProcessMessageResult *
+LaunchProcessMessageResult::Create(const LaunchProcessMessage *message)
+{
+    return new LaunchProcessMessageResult(message);
+}
+
+void
+LaunchProcessMessageResult::SetProcess(const HostProcess &process)
+{
+    m_process = process;
+}
Index: source/Plugins/Process/Windows/DebugMonitorMessageResults.h
===================================================================
--- /dev/null
+++ source/Plugins/Process/Windows/DebugMonitorMessageResults.h
@@ -0,0 +1,70 @@
+//===-- DebugMonitorMessages.h ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Plugins_Process_Windows_DebugMonitorMessageResults_H_
+#define liblldb_Plugins_Process_Windows_DebugMonitorMessageResults_H_
+
+#include "lldb/Core/Error.h"
+#include "lldb/Host/HostProcess.h"
+
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+
+namespace lldb_private
+{
+
+class DebugMonitorMessage;
+class DebugMonitorMessageResult;
+class LaunchProcessMessage;
+
+class DebugMonitorMessageResult : public llvm::ThreadSafeRefCountedBase<DebugMonitorMessageResult>
+{
+  public:
+    virtual ~DebugMonitorMessageResult();
+
+    const Error &
+    GetError() const
+    {
+        return m_error;
+    }
+    const DebugMonitorMessage *
+    GetOriginalMessage() const
+    {
+        return m_message;
+    }
+
+    void SetError(const Error &error);
+
+  protected:
+    explicit DebugMonitorMessageResult(const DebugMonitorMessage *message);
+
+  private:
+    Error m_error;
+    const DebugMonitorMessage *m_message;
+};
+
+class LaunchProcessMessageResult : public DebugMonitorMessageResult
+{
+  public:
+    static LaunchProcessMessageResult *Create(const LaunchProcessMessage *message);
+
+    void SetProcess(const HostProcess &process);
+    const HostProcess &
+    GetProcess() const
+    {
+        return m_process;
+    }
+
+  private:
+    LaunchProcessMessageResult(const LaunchProcessMessage *message);
+
+    HostProcess m_process;
+};
+}
+
+#endif
Index: source/Plugins/Process/Windows/DebugMonitorMessages.cpp
===================================================================
--- /dev/null
+++ source/Plugins/Process/Windows/DebugMonitorMessages.cpp
@@ -0,0 +1,62 @@
+//===-- DebugMonitorMessages.cpp --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DebugMonitorMessages.h"
+#include "DebugMonitorMessageResults.h"
+
+#include "lldb/Core/Error.h"
+#include "lldb/Host/HostProcess.h"
+#include "lldb/Target/ProcessLaunchInfo.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+DebugMonitorMessage::DebugMonitorMessage(MonitorMessageType message_type)
+    : m_message_type(message_type)
+{
+    Retain();
+    m_completion_predicate.SetValue(nullptr, eBroadcastNever);
+}
+
+DebugMonitorMessage::~DebugMonitorMessage()
+{
+    const DebugMonitorMessageResult *result = m_completion_predicate.GetValue();
+    if (result)
+        result->Release();
+    m_completion_predicate.SetValue(nullptr, eBroadcastNever);
+}
+
+const DebugMonitorMessageResult *
+DebugMonitorMessage::WaitForCompletion()
+{
+    const DebugMonitorMessageResult *result = nullptr;
+    m_completion_predicate.WaitForValueNotEqualTo(nullptr, result);
+    return result;
+}
+
+void
+DebugMonitorMessage::CompleteMessage(const DebugMonitorMessageResult *result)
+{
+    if (result)
+        result->Retain();
+    m_completion_predicate.SetValue(result, eBroadcastAlways);
+}
+
+LaunchProcessMessage::LaunchProcessMessage(const ProcessLaunchInfo &launch_info, lldb::ProcessSP process_plugin)
+    : DebugMonitorMessage(MonitorMessageType::eLaunchProcess)
+    , m_launch_info(launch_info)
+    , m_process_plugin(process_plugin)
+{
+}
+
+LaunchProcessMessage *
+LaunchProcessMessage::Create(const ProcessLaunchInfo &launch_info, lldb::ProcessSP process_plugin)
+{
+    return new LaunchProcessMessage(launch_info, process_plugin);
+}
Index: source/Plugins/Process/Windows/DebugMonitorMessages.h
===================================================================
--- /dev/null
+++ source/Plugins/Process/Windows/DebugMonitorMessages.h
@@ -0,0 +1,87 @@
+//===-- DebugMonitorMessages.h ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Plugins_Process_Windows_DebugMonitorMessages_H_
+#define liblldb_Plugins_Process_Windows_DebugMonitorMessages_H_
+
+#include "lldb/Host/Predicate.h"
+#include "lldb/Host/HostThread.h"
+#include "lldb/Host/ProcessStatusMonitor.h"
+#include "lldb/Host/windows/windows.h"
+#include "lldb/lldb-types.h"
+
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+
+#include <map>
+#include <memory>
+
+class ProcessWindows;
+
+namespace lldb_private
+{
+class DebugMonitorMessage;
+class DebugMonitorMessageResult;
+class ProcessLaunchInfo;
+
+enum class MonitorMessageType
+{
+    eLaunchProcess,  // Launch a process under the control of the debugger.
+    eAttachProcess,  // Attach to an existing process, and give control to the debugger.
+    eDetachProcess,  // Detach from a process that the debugger currently controls.
+    eSuspendProcess, // Suspend a process.
+    eResumeProcess,  // Resume a suspended process.
+};
+
+class DebugMonitorMessage : public llvm::ThreadSafeRefCountedBase<DebugMonitorMessage>
+{
+  public:
+    virtual ~DebugMonitorMessage();
+
+    const DebugMonitorMessageResult *WaitForCompletion();
+    void CompleteMessage(const DebugMonitorMessageResult *result);
+
+    MonitorMessageType
+    GetMessageType() const
+    {
+        return m_message_type;
+    }
+
+  protected:
+    explicit DebugMonitorMessage(MonitorMessageType message_type);
+
+  private:
+    Predicate<const DebugMonitorMessageResult *> m_completion_predicate;
+    MonitorMessageType m_message_type;
+};
+
+class LaunchProcessMessage : public DebugMonitorMessage
+{
+  public:
+    static LaunchProcessMessage *Create(const ProcessLaunchInfo &launch_info, lldb::ProcessSP m_process_plugin);
+    const ProcessLaunchInfo &
+    GetLaunchInfo() const
+    {
+        return m_launch_info;
+    }
+
+    lldb::ProcessSP
+    GetProcessPlugin() const
+    {
+        return m_process_plugin;
+    }
+
+  private:
+    LaunchProcessMessage(const ProcessLaunchInfo &launch_info, lldb::ProcessSP m_process_plugin);
+
+    const ProcessLaunchInfo &m_launch_info;
+    lldb::ProcessSP m_process_plugin;
+};
+}
+
+#endif
Index: source/Plugins/Process/Windows/DebugOneProcessThread.cpp
===================================================================
--- /dev/null
+++ source/Plugins/Process/Windows/DebugOneProcessThread.cpp
@@ -0,0 +1,227 @@
+//===-- DebugDriverThread.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DebugDriverThread.h"
+#include "DebugOneProcessThread.h"
+#include "DebugMonitorMessages.h"
+#include "DebugMonitorMessageResults.h"
+#include "SlaveMessages.h"
+
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Host/Predicate.h"
+#include "lldb/Host/ThisThread.h"
+#include "lldb/Host/ThreadLauncher.h"
+#include "lldb/Host/windows/HostThreadWindows.h"
+#include "lldb/Host/windows/ProcessLauncherWindows.h"
+
+#include "llvm/Support/raw_ostream.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace
+{
+struct DebugLaunchContext
+{
+    DebugOneProcessThread *instance;
+    const LaunchProcessMessage *launch;
+};
+}
+
+DebugOneProcessThread::DebugOneProcessThread(HostThread driver_thread)
+    : m_driver_thread(driver_thread)
+{
+    m_launch_predicate.SetValue(nullptr, eBroadcastNever);
+}
+
+DebugOneProcessThread::~DebugOneProcessThread()
+{
+}
+
+const LaunchProcessMessageResult *
+DebugOneProcessThread::DebugLaunch(const LaunchProcessMessage *message)
+{
+    Error error;
+    const LaunchProcessMessageResult *result = nullptr;
+    DebugLaunchContext context;
+    context.instance = this;
+    context.launch = message;
+
+    HostThread slave_thread(ThreadLauncher::LaunchThread("lldb.plugin.process-windows.slave[?]", DebugLaunchThread, &context, &error));
+    if (error.Success())
+        m_launch_predicate.WaitForValueNotEqualTo(nullptr, result);
+
+    return result;
+}
+
+lldb::thread_result_t
+DebugOneProcessThread::DebugLaunchThread(void *data)
+{
+    DebugLaunchContext *context = static_cast<DebugLaunchContext *>(data);
+    DebugOneProcessThread *thread = context->instance;
+    return thread->DebugLaunchThread(context->launch);
+}
+
+lldb::thread_result_t
+DebugOneProcessThread::DebugLaunchThread(const LaunchProcessMessage *message)
+{
+    // Grab a shared_ptr reference to this so that we know it won't get deleted until after the
+    // thread routine has exited.
+    std::shared_ptr<DebugOneProcessThread> this_ref(shared_from_this());
+    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+    Error error;
+    ProcessLauncherWindows launcher;
+
+    m_process_plugin = message->GetProcessPlugin();
+    m_process = launcher.LaunchProcess(message->GetLaunchInfo(), error);
+
+    std::string thread_name;
+    llvm::raw_string_ostream name_stream(thread_name);
+    name_stream << "lldb.plugin.process-windows.slave[" << m_process.GetProcessId() << "]";
+    name_stream.flush();
+    ThisThread::SetName(thread_name.c_str());
+
+    LaunchProcessMessageResult *result = LaunchProcessMessageResult::Create(message);
+    result->SetError(error);
+    result->SetProcess(m_process);
+    m_launch_predicate.SetValue(result, eBroadcastAlways);
+
+    DebugLoop();
+    if (log)
+        log->Printf("Debug monitor thread '%s' exiting.", thread_name.c_str());
+
+    return 0;
+}
+
+void
+DebugOneProcessThread::DebugLoop()
+{
+    DEBUG_EVENT dbe = {0};
+    bool exit = false;
+    while (!exit && WaitForDebugEvent(&dbe, INFINITE))
+    {
+        DWORD continue_status = DBG_CONTINUE;
+        switch (dbe.dwDebugEventCode)
+        {
+            case EXCEPTION_DEBUG_EVENT:
+                continue_status = HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId);
+                break;
+            case CREATE_THREAD_DEBUG_EVENT:
+                continue_status = HandleCreateThreadEvent(dbe.u.CreateThread, dbe.dwThreadId);
+                break;
+            case CREATE_PROCESS_DEBUG_EVENT:
+                continue_status = HandleCreateProcessEvent(dbe.u.CreateProcessInfo, dbe.dwThreadId);
+                break;
+            case EXIT_THREAD_DEBUG_EVENT:
+                continue_status = HandleExitThreadEvent(dbe.u.ExitThread, dbe.dwThreadId);
+                break;
+            case EXIT_PROCESS_DEBUG_EVENT:
+                continue_status = HandleExitProcessEvent(dbe.u.ExitProcess, dbe.dwThreadId);
+                exit = true;
+                break;
+            case LOAD_DLL_DEBUG_EVENT:
+                continue_status = HandleLoadDllEvent(dbe.u.LoadDll, dbe.dwThreadId);
+                break;
+            case UNLOAD_DLL_DEBUG_EVENT:
+                continue_status = HandleUnloadDllEvent(dbe.u.UnloadDll, dbe.dwThreadId);
+                break;
+            case OUTPUT_DEBUG_STRING_EVENT:
+                continue_status = HandleODSEvent(dbe.u.DebugString, dbe.dwThreadId);
+                break;
+            case RIP_EVENT:
+                continue_status = HandleRipEvent(dbe.u.RipInfo, dbe.dwThreadId);
+                if (dbe.u.RipInfo.dwType == SLE_ERROR)
+                    exit = true;
+                break;
+        }
+
+        ::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId, continue_status);
+    }
+}
+
+DWORD
+DebugOneProcessThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, DWORD thread_id)
+{
+    return DBG_CONTINUE;
+}
+
+DWORD
+DebugOneProcessThread::HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, DWORD thread_id)
+{
+    return DBG_CONTINUE;
+}
+
+DWORD
+DebugOneProcessThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, DWORD thread_id)
+{
+    return DBG_CONTINUE;
+}
+
+DWORD
+DebugOneProcessThread::HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, DWORD thread_id)
+{
+    return DBG_CONTINUE;
+}
+
+DWORD
+DebugOneProcessThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, DWORD thread_id)
+{
+    HANDLE driver = m_driver_thread.GetNativeThread().GetSystemHandle();
+    SlaveMessageProcessExited *message = new SlaveMessageProcessExited(m_process, info.dwExitCode);
+
+    QueueUserAPC(NotifySlaveProcessExited, driver, reinterpret_cast<ULONG_PTR>(message));
+    return DBG_CONTINUE;
+}
+
+DWORD
+DebugOneProcessThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, DWORD thread_id)
+{
+    return DBG_CONTINUE;
+}
+
+DWORD
+DebugOneProcessThread::HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, DWORD thread_id)
+{
+    return DBG_CONTINUE;
+}
+
+DWORD
+DebugOneProcessThread::HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, DWORD thread_id)
+{
+    return DBG_CONTINUE;
+}
+
+DWORD
+DebugOneProcessThread::HandleRipEvent(const RIP_INFO &info, DWORD thread_id)
+{
+    HANDLE driver = m_driver_thread.GetNativeThread().GetSystemHandle();
+    Error error(info.dwError, eErrorTypeWin32);
+    SlaveMessageRipEvent *message = new SlaveMessageRipEvent(m_process, error, info.dwType);
+
+    QueueUserAPC(NotifySlaveRipEvent, driver, reinterpret_cast<ULONG_PTR>(message));
+    return DBG_CONTINUE;
+}
+
+void
+DebugOneProcessThread::NotifySlaveProcessExited(ULONG_PTR message)
+{
+    SlaveMessageProcessExited *slave_message = reinterpret_cast<SlaveMessageProcessExited *>(message);
+    DebugDriverThread::GetInstance().HandleSlaveEvent(*slave_message);
+    delete slave_message;
+}
+
+void
+DebugOneProcessThread::NotifySlaveRipEvent(ULONG_PTR message)
+{
+    SlaveMessageRipEvent *slave_message = reinterpret_cast<SlaveMessageRipEvent *>(message);
+    DebugDriverThread::GetInstance().HandleSlaveEvent(*slave_message);
+    delete slave_message;
+}
Index: source/Plugins/Process/Windows/DebugOneProcessThread.h
===================================================================
--- /dev/null
+++ source/Plugins/Process/Windows/DebugOneProcessThread.h
@@ -0,0 +1,63 @@
+//===-- DebugOneProcessThread.h ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Plugins_Process_Windows_DebugOneProcessThread_H_
+#define liblldb_Plugins_Process_Windows_DebugOneProcessThread_H_
+
+#include "lldb/Host/HostProcess.h"
+#include "lldb/Host/HostThread.h"
+#include "lldb/Host/Predicate.h"
+#include "lldb/Host/windows/windows.h"
+
+namespace lldb_private
+{
+class LaunchProcessMessage;
+class LaunchProcessMessageResult;
+
+//----------------------------------------------------------------------
+// DebugOneProcessThread
+//
+// Debugs a single process, notifying the process plugin and/or the debugger
+// driver thread as appropriate when interesting things occur.
+//----------------------------------------------------------------------
+class DebugOneProcessThread : public std::enable_shared_from_this<DebugOneProcessThread>
+{
+  public:
+    DebugOneProcessThread(HostThread driver_thread);
+    virtual ~DebugOneProcessThread();
+
+    const LaunchProcessMessageResult *DebugLaunch(const LaunchProcessMessage *message);
+
+  private:
+    void DebugLoop();
+    DWORD HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, DWORD thread_id);
+    DWORD HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, DWORD thread_id);
+    DWORD HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, DWORD thread_id);
+    DWORD HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, DWORD thread_id);
+    DWORD HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, DWORD thread_id);
+    DWORD HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, DWORD thread_id);
+    DWORD HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, DWORD thread_id);
+    DWORD HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, DWORD thread_id);
+    DWORD HandleRipEvent(const RIP_INFO &info, DWORD thread_id);
+
+    static void __stdcall NotifySlaveProcessExited(ULONG_PTR message);
+    static void __stdcall NotifySlaveRipEvent(ULONG_PTR message);
+
+    // The main debug driver thread which is controlling this slave.
+    lldb_private::HostThread m_driver_thread;
+    Predicate<const LaunchProcessMessageResult *> m_launch_predicate;
+    lldb::ProcessSP m_process_plugin;
+    HostProcess m_process;
+
+    static lldb::thread_result_t DebugLaunchThread(void *data);
+    lldb::thread_result_t DebugLaunchThread(const LaunchProcessMessage *message);
+};
+}
+
+#endif
Index: source/Plugins/Process/Windows/DebugProcessLauncher.cpp
===================================================================
--- /dev/null
+++ source/Plugins/Process/Windows/DebugProcessLauncher.cpp
@@ -0,0 +1,38 @@
+//===-- DebugProcessLauncher.cpp --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DebugDriverThread.h"
+#include "DebugMonitorMessages.h"
+#include "DebugMonitorMessageResults.h"
+#include "DebugProcessLauncher.h"
+
+#include "lldb/Core/Error.h"
+#include "lldb/Host/HostProcess.h"
+#include "lldb/Target/ProcessLaunchInfo.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+DebugProcessLauncher::DebugProcessLauncher(lldb::ProcessSP process_plugin)
+    : m_process_plugin(process_plugin)
+{
+}
+
+HostProcess
+DebugProcessLauncher::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error)
+{
+    LaunchProcessMessage *message = LaunchProcessMessage::Create(launch_info, m_process_plugin);
+    DebugDriverThread::GetInstance().PostDebugMessage(message);
+    const LaunchProcessMessageResult *result = static_cast<const LaunchProcessMessageResult *>(message->WaitForCompletion());
+    error = result->GetError();
+    HostProcess process = result->GetProcess();
+
+    message->Release();
+    return process;
+}
Index: source/Plugins/Process/Windows/DebugProcessLauncher.h
===================================================================
--- /dev/null
+++ source/Plugins/Process/Windows/DebugProcessLauncher.h
@@ -0,0 +1,40 @@
+//===-- DebugProcessLauncher.h ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Plugins_Process_Windows_DebugProcessLauncher_H_
+#define liblldb_Plugins_Process_Windows_DebugProcessLauncher_H_
+
+#include "lldb/Host/ProcessLauncher.h"
+#include "lldb/lldb-forward.h"
+
+namespace lldb_private
+{
+
+//----------------------------------------------------------------------
+// DebugProcessLauncher
+//
+// DebugProcessLauncher launches a process for debugging on Windows.  On
+// Windows, the debug loop that detects events and status changes in a debugged
+// process must run on the same thread that calls CreateProcess.  So
+// DebugProcessLauncher is built with this in mind.  It queues a request to the
+// DebugDriverThread to launch a new process, then waits for a notification from
+// that thread that the launch is complete.
+//----------------------------------------------------------------------
+class DebugProcessLauncher : public ProcessLauncher
+{
+  public:
+    explicit DebugProcessLauncher(lldb::ProcessSP process_plugin);
+    virtual HostProcess LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error);
+
+  private:
+    lldb::ProcessSP m_process_plugin;
+};
+}
+
+#endif
Index: source/Plugins/Process/Windows/ProcessWindows.cpp
===================================================================
--- source/Plugins/Process/Windows/ProcessWindows.cpp
+++ source/Plugins/Process/Windows/ProcessWindows.cpp
@@ -11,18 +11,26 @@
 #include "lldb/Host/windows/windows.h"
 
 // C++ Includes
+#include <vector>
+
 // Other libraries and framework includes
 #include "lldb/Core/Module.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/State.h"
 #include "lldb/Host/Host.h"
 #include "lldb/Host/HostProcess.h"
+#include "lldb/Host/MonitoringProcessLauncher.h"
+#include "lldb/Host/ProcessStatusMonitor.h"
+#include "lldb/Host/ThreadLauncher.h"
+#include "lldb/Host/windows/ExitStatusMonitorWindows.h"
 #include "lldb/Host/windows/ProcessLauncherWindows.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Target/DynamicLoader.h"
 #include "lldb/Target/FileAction.h"
 #include "lldb/Target/Target.h"
 
+#include "DebugDriverThread.h"
+#include "DebugProcessLauncher.h"
 #include "ProcessWindows.h"
 
 using namespace lldb;
@@ -48,6 +56,7 @@
         PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                       GetPluginDescriptionStatic(),
                                       CreateInstance);
+        DebugDriverThread::Initialize();
     }
 }
 
@@ -59,9 +68,14 @@
 {
 }
 
+ProcessWindows::~ProcessWindows()
+{
+}
+
 void
 ProcessWindows::Terminate()
 {
+    DebugDriverThread::Teardown();
 }
 
 lldb_private::ConstString
@@ -89,7 +103,35 @@
 ProcessWindows::DoLaunch(Module *exe_module,
                          ProcessLaunchInfo &launch_info)
 {
-    return Host::LaunchProcess(launch_info);
+    Error result;
+    HostProcess process;
+    SetPrivateState(eStateLaunching);
+    if (launch_info.GetFlags().Test(eLaunchFlagDebug))
+    {
+        // If we're trying to debug this process, we need to use a
+        // DebugProcessLauncher so that we can enter a WaitForDebugEvent loop
+        // on the same thread that does the CreateProcess.
+        DebugProcessLauncher launcher(shared_from_this());
+        process = launcher.LaunchProcess(launch_info, result);
+    }
+    else
+    {
+        // If we're not trying to debug this process, use a standard launcher
+        // and only monitor for the process's exit, and not other types of debug
+        // events.
+        ProcessLauncherWindows delegate_launcher;
+        ProcessStatusMonitorSP status_monitor;
+        status_monitor.reset(new ExitStatusMonitor());
+        MonitoringProcessLauncher launcher(status_monitor, delegate_launcher);
+        process = launcher.LaunchProcess(launch_info, result);
+    }
+
+    if (!result.Success())
+        return result;
+
+    launch_info.SetProcessID(process.GetProcessId());
+    SetID(process.GetProcessId());
+    return result;
 }
 
 Error
@@ -181,4 +223,3 @@
         return exe_module_sp->GetFileSpec().Exists();
     return false;
 }
-
Index: source/Plugins/Process/Windows/ProcessWindows.h
===================================================================
--- source/Plugins/Process/Windows/ProcessWindows.h
+++ source/Plugins/Process/Windows/ProcessWindows.h
@@ -13,13 +13,21 @@
 // C Includes
 
 // C++ Includes
+#include <map>
 #include <queue>
 
 // Other libraries and framework includes
+#include "lldb/Host/HostThread.h"
+#include "lldb/Host/ProcessStatusMonitor.h"
 #include "lldb/Target/Process.h"
 
 class ProcessMonitor;
 
+namespace lldb_private
+{
+class HostProcess;
+}
+
 class ProcessWindows :
     public lldb_private::Process
 {
@@ -50,6 +58,8 @@
     ProcessWindows(lldb_private::Target& target,
                    lldb_private::Listener &listener);
 
+    ~ProcessWindows();
+
     virtual lldb_private::Error
     DoDetach(bool keep_stopped);
 
@@ -99,11 +109,7 @@
     virtual bool
     IsAlive ();
 
-    virtual size_t
-    DoReadMemory (lldb::addr_t vm_addr, 
-                  void *buf, 
-                  size_t size,
-                  lldb_private::Error &error);
+    virtual size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, lldb_private::Error &error);
 };
 
 #endif  // liblldb_Plugins_Process_Windows_ProcessWindows_H_
Index: source/Plugins/Process/Windows/SlaveMessages.h
===================================================================
--- /dev/null
+++ source/Plugins/Process/Windows/SlaveMessages.h
@@ -0,0 +1,92 @@
+//===-- SlaveMessages.h -----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Plugins_Process_Windows_SlaveMessages_H_
+#define liblldb_Plugins_Process_Windows_SlaveMessages_H_
+
+#include "lldb/Core/Error.h"
+#include "lldb/Host/HostProcess.h"
+
+namespace lldb_private
+{
+
+//----------------------------------------------------------------------
+// SlaveMessageBase
+//
+// SlaveMessageBase serves as a base class for all messages which debug slaves
+// can send up to the driver thread to notify it of events related to processes
+// which are being debugged.
+//----------------------------------------------------------------------
+class SlaveMessageBase
+{
+  public:
+    SlaveMessageBase(const HostProcess &process)
+        : m_process(process)
+    {
+    }
+
+    virtual ~SlaveMessageBase() {}
+
+    const HostProcess &
+    GetProcess() const
+    {
+        return m_process;
+    }
+
+  protected:
+    HostProcess m_process;
+};
+
+class SlaveMessageProcessExited : public SlaveMessageBase
+{
+  public:
+    SlaveMessageProcessExited(const HostProcess &process, DWORD exit_code)
+        : SlaveMessageBase(process)
+        , m_exit_code(exit_code)
+    {
+    }
+
+    DWORD
+    GetExitCode() const
+    {
+        return m_exit_code;
+    }
+
+  private:
+    DWORD m_exit_code;
+};
+
+class SlaveMessageRipEvent : public SlaveMessageBase
+{
+  public:
+    SlaveMessageRipEvent(const HostProcess &process, const Error &error, DWORD type)
+        : SlaveMessageBase(process)
+        , m_error(error)
+        , m_type(type)
+    {
+    }
+
+    const Error &
+    GetError() const
+    {
+        return m_error;
+    }
+    DWORD
+    GetType() const
+    {
+        return m_type;
+    }
+
+  private:
+    Error m_error;
+    DWORD m_type;
+};
+}
+
+#endif
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits

Reply via email to