Index: lldb/trunk/include/lldb/Host/ThreadLauncher.h =================================================================== --- lldb/trunk/include/lldb/Host/ThreadLauncher.h +++ lldb/trunk/include/lldb/Host/ThreadLauncher.h @@ -1,5 +1,4 @@ -//===-- ThreadLauncher.h -----------------------------------------*- C++ -//-*-===// +//===-- ThreadLauncher.h ----------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -11,18 +10,18 @@ #define lldb_Host_ThreadLauncher_h_ #include "lldb/Host/HostThread.h" -#include "lldb/Utility/Status.h" #include "lldb/lldb-types.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" namespace lldb_private { class ThreadLauncher { public: - static HostThread + static llvm::Expected LaunchThread(llvm::StringRef name, lldb::thread_func_t thread_function, - lldb::thread_arg_t thread_arg, Status *error_ptr, + lldb::thread_arg_t thread_arg, size_t min_stack_byte_size = 0); // Minimum stack size in bytes, // set stack size to zero for // default platform thread stack Index: lldb/trunk/source/API/SBHostOS.cpp =================================================================== --- lldb/trunk/source/API/SBHostOS.cpp +++ lldb/trunk/source/API/SBHostOS.cpp @@ -107,10 +107,17 @@ LLDB_RECORD_DUMMY(lldb::thread_t, SBHostOS, ThreadCreate, (lldb::thread_func_t, void *, SBError *), name, thread_function, thread_arg, error_ptr); - HostThread thread( - ThreadLauncher::LaunchThread(name, thread_function, thread_arg, - error_ptr ? error_ptr->get() : nullptr)); - return thread.Release(); + llvm::Expected thread = + ThreadLauncher::LaunchThread(name, thread_function, thread_arg); + if (!thread) { + if (error_ptr) + error_ptr->SetError(Status(thread.takeError())); + else + llvm::consumeError(thread.takeError()); + return LLDB_INVALID_HOST_THREAD; + } + + return thread->Release(); } void SBHostOS::ThreadCreated(const char *name) { Index: lldb/trunk/source/Core/Communication.cpp =================================================================== --- lldb/trunk/source/Core/Communication.cpp +++ lldb/trunk/source/Core/Communication.cpp @@ -204,10 +204,23 @@ m_read_thread_enabled = true; m_read_thread_did_exit = false; - m_read_thread = ThreadLauncher::LaunchThread( - thread_name, Communication::ReadThread, this, error_ptr); + auto maybe_thread = ThreadLauncher::LaunchThread( + thread_name, Communication::ReadThread, this); + if (maybe_thread) { + m_read_thread = *maybe_thread; + } else { + if (error_ptr) + *error_ptr = Status(maybe_thread.takeError()); + else { + LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), + "failed to launch host thread: {}", + llvm::toString(maybe_thread.takeError())); + } + } + if (!m_read_thread.IsJoinable()) m_read_thread_enabled = false; + return m_read_thread_enabled; } Index: lldb/trunk/source/Core/Debugger.cpp =================================================================== --- lldb/trunk/source/Core/Debugger.cpp +++ lldb/trunk/source/Core/Debugger.cpp @@ -1642,8 +1642,17 @@ full_name.AsCString() : "dbg.evt-handler"; // Use larger 8MB stack for this thread - m_event_handler_thread = ThreadLauncher::LaunchThread(thread_name, - EventHandlerThread, this, nullptr, g_debugger_event_thread_stack_bytes); + llvm::Expected event_handler_thread = + ThreadLauncher::LaunchThread(thread_name, EventHandlerThread, this, + g_debugger_event_thread_stack_bytes); + + if (event_handler_thread) { + m_event_handler_thread = *event_handler_thread; + } else { + LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), + "failed to launch host thread: {}", + llvm::toString(event_handler_thread.takeError())); + } // Make sure DefaultEventHandler() is running and listening to events // before we return from this function. We are only listening for events of @@ -1674,10 +1683,18 @@ bool Debugger::HasIOHandlerThread() { return m_io_handler_thread.IsJoinable(); } bool Debugger::StartIOHandlerThread() { - if (!m_io_handler_thread.IsJoinable()) - m_io_handler_thread = ThreadLauncher::LaunchThread( - "lldb.debugger.io-handler", IOHandlerThread, this, nullptr, + if (!m_io_handler_thread.IsJoinable()) { + llvm::Expected io_handler_thread = ThreadLauncher::LaunchThread( + "lldb.debugger.io-handler", IOHandlerThread, this, 8 * 1024 * 1024); // Use larger 8MB stack for this thread + if (io_handler_thread) { + m_io_handler_thread = *io_handler_thread; + } else { + LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), + "failed to launch host thread: {}", + llvm::toString(io_handler_thread.takeError())); + } + } return m_io_handler_thread.IsJoinable(); } Index: lldb/trunk/source/Host/common/TaskPool.cpp =================================================================== --- lldb/trunk/source/Host/common/TaskPool.cpp +++ lldb/trunk/source/Host/common/TaskPool.cpp @@ -8,6 +8,7 @@ #include "lldb/Host/TaskPool.h" #include "lldb/Host/ThreadLauncher.h" +#include "lldb/Utility/Log.h" #include #include @@ -65,9 +66,16 @@ // Note that this detach call needs to happen with the m_tasks_mutex held. // This prevents the thread from exiting prematurely and triggering a linux // libc bug (https://sourceware.org/bugzilla/show_bug.cgi?id=19951). - lldb_private::ThreadLauncher::LaunchThread("task-pool.worker", WorkerPtr, - this, nullptr, min_stack_size) - .Release(); + llvm::Expected host_thread = + lldb_private::ThreadLauncher::LaunchThread( + "task-pool.worker", WorkerPtr, this, min_stack_size); + if (host_thread) { + host_thread->Release(); + } else { + LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), + "failed to launch host thread: {}", + llvm::toString(host_thread.takeError())); + } } } Index: lldb/trunk/source/Host/common/ThreadLauncher.cpp =================================================================== --- lldb/trunk/source/Host/common/ThreadLauncher.cpp +++ lldb/trunk/source/Host/common/ThreadLauncher.cpp @@ -20,15 +20,9 @@ using namespace lldb; using namespace lldb_private; -HostThread ThreadLauncher::LaunchThread(llvm::StringRef name, - lldb::thread_func_t thread_function, - lldb::thread_arg_t thread_arg, - Status *error_ptr, - size_t min_stack_byte_size) { - Status error; - if (error_ptr) - error_ptr->Clear(); - +llvm::Expected ThreadLauncher::LaunchThread( + llvm::StringRef name, lldb::thread_func_t thread_function, + lldb::thread_arg_t thread_arg, size_t min_stack_byte_size) { // Host::ThreadCreateTrampoline will delete this pointer for us. HostThreadCreateInfo *info_ptr = new HostThreadCreateInfo(name.data(), thread_function, thread_arg); @@ -38,7 +32,7 @@ 0, (unsigned)min_stack_byte_size, HostNativeThread::ThreadCreateTrampoline, info_ptr, 0, NULL); if (thread == (lldb::thread_t)(-1L)) - error.SetError(::GetLastError(), eErrorTypeWin32); + return llvm::errorCodeToError(::GetLastError()); #else // ASAN instrumentation adds a lot of bookkeeping overhead on stack frames. @@ -73,12 +67,10 @@ if (destroy_attr) ::pthread_attr_destroy(&thread_attr); - error.SetError(err, eErrorTypePOSIX); + if (err) + return llvm::errorCodeToError( + std::error_code(err, std::generic_category())); #endif - if (error_ptr) - *error_ptr = error; - if (!error.Success()) - thread = LLDB_INVALID_HOST_THREAD; return HostThread(thread); } Index: lldb/trunk/source/Host/macosx/objcxx/Host.mm =================================================================== --- lldb/trunk/source/Host/macosx/objcxx/Host.mm +++ lldb/trunk/source/Host/macosx/objcxx/Host.mm @@ -313,13 +313,16 @@ // in a shell and the shell will fork/exec a couple of times before we get // to the process that we wanted to launch. So when our process actually // gets launched, we will handshake with it and get the process ID for it. - HostThread accept_thread = ThreadLauncher::LaunchThread( - unix_socket_name, AcceptPIDFromInferior, connect_url, &lldb_error); + llvm::Expected accept_thread = ThreadLauncher::LaunchThread( + unix_socket_name, AcceptPIDFromInferior, connect_url); + + if (!accept_thread) + return Status(accept_thread.takeError()); [applescript executeAndReturnError:nil]; thread_result_t accept_thread_result = NULL; - lldb_error = accept_thread.Join(&accept_thread_result); + lldb_error = accept_thread->Join(&accept_thread_result); if (lldb_error.Success() && accept_thread_result) { pid = (intptr_t)accept_thread_result; Index: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp @@ -32,6 +32,7 @@ #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/Log.h" #include "lldb/Utility/State.h" #include "lldb/Utility/StringExtractor.h" #include "lldb/Utility/UUID.h" @@ -739,8 +740,15 @@ if (m_async_thread.IsJoinable()) return true; - m_async_thread = ThreadLauncher::LaunchThread( - "", ProcessKDP::AsyncThread, this, NULL); + llvm::Expected async_thread = ThreadLauncher::LaunchThread( + "", ProcessKDP::AsyncThread, this); + if (!async_thread) { + LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), + "failed to launch host thread: {}", + llvm::toString(async_thread.takeError())); + return false; + } + m_async_thread = *async_thread; return m_async_thread.IsJoinable(); } Index: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -888,22 +888,23 @@ Status GDBRemoteCommunication::StartListenThread(const char *hostname, uint16_t port) { - Status error; - if (m_listen_thread.IsJoinable()) { - error.SetErrorString("listen thread already running"); - } else { - char listen_url[512]; - if (hostname && hostname[0]) - snprintf(listen_url, sizeof(listen_url), "listen://%s:%i", hostname, - port); - else - snprintf(listen_url, sizeof(listen_url), "listen://%i", port); - m_listen_url = listen_url; - SetConnection(new ConnectionFileDescriptor()); - m_listen_thread = ThreadLauncher::LaunchThread( - listen_url, GDBRemoteCommunication::ListenThread, this, &error); - } - return error; + if (m_listen_thread.IsJoinable()) + return Status("listen thread already running"); + + char listen_url[512]; + if (hostname && hostname[0]) + snprintf(listen_url, sizeof(listen_url), "listen://%s:%i", hostname, port); + else + snprintf(listen_url, sizeof(listen_url), "listen://%i", port); + m_listen_url = listen_url; + SetConnection(new ConnectionFileDescriptor()); + llvm::Expected listen_thread = ThreadLauncher::LaunchThread( + listen_url, GDBRemoteCommunication::ListenThread, this); + if (!listen_thread) + return Status(listen_thread.takeError()); + m_listen_thread = *listen_thread; + + return Status(); } bool GDBRemoteCommunication::JoinListenThread() { Index: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp @@ -203,9 +203,16 @@ if (!m_async_thread.IsJoinable()) { // Create a thread that watches our internal state and controls which // events make it to clients (into the DCProcess event queue). - m_async_thread = ThreadLauncher::LaunchThread( + llvm::Expected async_thread = ThreadLauncher::LaunchThread( "", - GDBRemoteCommunicationReplayServer::AsyncThread, this, nullptr); + GDBRemoteCommunicationReplayServer::AsyncThread, this); + if (!async_thread) { + LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), + "failed to launch host thread: {}", + llvm::toString(async_thread.takeError())); + return false; + } + m_async_thread = *async_thread; } // Wait for handshake. Index: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -3700,9 +3700,15 @@ // Create a thread that watches our internal state and controls which // events make it to clients (into the DCProcess event queue). - m_async_thread = ThreadLauncher::LaunchThread( - "", ProcessGDBRemote::AsyncThread, this, - nullptr); + llvm::Expected async_thread = ThreadLauncher::LaunchThread( + "", ProcessGDBRemote::AsyncThread, this); + if (!async_thread) { + LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), + "failed to launch host thread: {}", + llvm::toString(async_thread.takeError())); + return false; + } + m_async_thread = *async_thread; } else if (log) log->Printf("ProcessGDBRemote::%s () - Called when Async thread was " "already running.", Index: lldb/trunk/source/Target/Process.cpp =================================================================== --- lldb/trunk/source/Target/Process.cpp +++ lldb/trunk/source/Target/Process.cpp @@ -3588,14 +3588,20 @@ // Create the private state thread, and start it running. PrivateStateThreadArgs *args_ptr = new PrivateStateThreadArgs(this, is_secondary_thread); - m_private_state_thread = + llvm::Expected private_state_thread = ThreadLauncher::LaunchThread(thread_name, Process::PrivateStateThread, - (void *)args_ptr, nullptr, 8 * 1024 * 1024); - if (m_private_state_thread.IsJoinable()) { - ResumePrivateStateThread(); - return true; - } else + (void *)args_ptr, 8 * 1024 * 1024); + if (!private_state_thread) { + LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), + "failed to launch host thread: {}", + llvm::toString(private_state_thread.takeError())); return false; + } + + assert(private_state_thread->IsJoinable()); + m_private_state_thread = *private_state_thread; + ResumePrivateStateThread(); + return true; } void Process::PausePrivateStateThread() {