Skip to content

Commit

Permalink
Change LaunchThread interface to return an expected.
Browse files Browse the repository at this point in the history
Change the interface to return an expected, instead of taking a Status
pointer.

Differential revision: https://reviews.llvm.org/D64163

llvm-svn: 365226
  • Loading branch information
JDevlieghere committed Jul 5, 2019
1 parent 6e6d229 commit f39c2e1
Show file tree
Hide file tree
Showing 12 changed files with 133 additions and 66 deletions.
9 changes: 4 additions & 5 deletions lldb/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.
Expand All @@ -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<HostThread>
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
Expand Down
15 changes: 11 additions & 4 deletions lldb/source/API/SBHostOS.cpp
Expand Up @@ -107,10 +107,17 @@ lldb::thread_t SBHostOS::ThreadCreate(const char *name,
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<HostThread> 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) {
Expand Down
17 changes: 15 additions & 2 deletions lldb/source/Core/Communication.cpp
Expand Up @@ -204,10 +204,23 @@ bool Communication::StartReadThread(Status *error_ptr) {

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;
}

Expand Down
27 changes: 22 additions & 5 deletions lldb/source/Core/Debugger.cpp
Expand Up @@ -1642,8 +1642,17 @@ bool Debugger::StartEventHandlerThread() {
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<HostThread> 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
Expand Down Expand Up @@ -1674,10 +1683,18 @@ lldb::thread_result_t Debugger::IOHandlerThread(lldb::thread_arg_t arg) {
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<HostThread> 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();
}

Expand Down
14 changes: 11 additions & 3 deletions lldb/source/Host/common/TaskPool.cpp
Expand Up @@ -8,6 +8,7 @@

#include "lldb/Host/TaskPool.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Utility/Log.h"

#include <cstdint>
#include <queue>
Expand Down Expand Up @@ -65,9 +66,16 @@ void TaskPoolImpl::AddTask(std::function<void()> &&task_fn) {
// 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<HostThread> 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()));
}
}
}

Expand Down
22 changes: 7 additions & 15 deletions lldb/source/Host/common/ThreadLauncher.cpp
Expand Up @@ -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<HostThread> 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);
Expand All @@ -38,7 +32,7 @@ HostThread ThreadLauncher::LaunchThread(llvm::StringRef name,
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.
Expand Down Expand Up @@ -73,12 +67,10 @@ HostThread ThreadLauncher::LaunchThread(llvm::StringRef name,
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);
}
9 changes: 6 additions & 3 deletions lldb/source/Host/macosx/objcxx/Host.mm
Expand Up @@ -313,13 +313,16 @@ repeat with the_window in (get windows)\n\
// 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<HostThread> 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;

Expand Down
12 changes: 10 additions & 2 deletions lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -739,8 +740,15 @@ bool ProcessKDP::StartAsyncThread() {
if (m_async_thread.IsJoinable())
return true;

m_async_thread = ThreadLauncher::LaunchThread(
"<lldb.process.kdp-remote.async>", ProcessKDP::AsyncThread, this, NULL);
llvm::Expected<HostThread> async_thread = ThreadLauncher::LaunchThread(
"<lldb.process.kdp-remote.async>", 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();
}

Expand Down
33 changes: 17 additions & 16 deletions lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
Expand Up @@ -888,22 +888,23 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,

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<HostThread> 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() {
Expand Down
Expand Up @@ -203,9 +203,16 @@ bool GDBRemoteCommunicationReplayServer::StartAsyncThread() {
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<HostThread> async_thread = ThreadLauncher::LaunchThread(
"<lldb.gdb-replay.async>",
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.
Expand Down
12 changes: 9 additions & 3 deletions lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
Expand Up @@ -3700,9 +3700,15 @@ bool ProcessGDBRemote::StartAsyncThread() {
// 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(
"<lldb.process.gdb-remote.async>", ProcessGDBRemote::AsyncThread, this,
nullptr);
llvm::Expected<HostThread> async_thread = ThreadLauncher::LaunchThread(
"<lldb.process.gdb-remote.async>", 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.",
Expand Down
18 changes: 12 additions & 6 deletions lldb/source/Target/Process.cpp
Expand Up @@ -3588,14 +3588,20 @@ bool Process::StartPrivateStateThread(bool is_secondary_thread) {
// Create the private state thread, and start it running.
PrivateStateThreadArgs *args_ptr =
new PrivateStateThreadArgs(this, is_secondary_thread);
m_private_state_thread =
llvm::Expected<HostThread> 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() {
Expand Down

0 comments on commit f39c2e1

Please sign in to comment.