/// \b True if the read thread is running, \b false otherwise.
bool ReadThreadIsRunning();
- /// The static read thread function. This function will call the "DoRead"
+ /// The read thread function. This function will call the "DoRead"
/// function continuously and wait for data to become available. When data
/// is received it will append the available data to the internal cache and
/// broadcast a \b eBroadcastBitReadThreadGotBytes event.
/// \b NULL.
///
/// \see void Communication::ReadThreadGotBytes (const uint8_t *, size_t);
- static lldb::thread_result_t ReadThread(lldb::thread_arg_t comm_ptr);
+ lldb::thread_result_t ReadThread();
void SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived callback,
void *callback_baton);
void StopEventHandlerThread();
- static lldb::thread_result_t EventHandlerThread(lldb::thread_arg_t arg);
-
void PushIOHandler(const lldb::IOHandlerSP &reader_sp,
bool cancel_top_handler = true);
void JoinIOHandlerThread();
- static lldb::thread_result_t IOHandlerThread(lldb::thread_arg_t arg);
+ lldb::thread_result_t IOHandlerThread();
- void DefaultEventHandler();
+ lldb::thread_result_t DefaultEventHandler();
void HandleBreakpointEvent(const lldb::EventSP &event_sp);
class ThreadLauncher {
public:
static llvm::Expected<HostThread>
- LaunchThread(llvm::StringRef name, lldb::thread_func_t thread_function,
- lldb::thread_arg_t thread_arg,
+ LaunchThread(llvm::StringRef name,
+ std::function<lldb::thread_result_t()> thread_function,
size_t min_stack_byte_size = 0); // Minimum stack size in bytes,
// set stack size to zero for
// default platform thread stack
struct HostThreadCreateInfo {
std::string thread_name;
- lldb::thread_func_t thread_fptr;
- lldb::thread_arg_t thread_arg;
+ std::function<lldb::thread_result_t()> impl;
- HostThreadCreateInfo(const char *name, lldb::thread_func_t fptr,
- lldb::thread_arg_t arg)
- : thread_name(name ? name : ""), thread_fptr(fptr), thread_arg(arg) {}
+ HostThreadCreateInfo(std::string thread_name,
+ std::function<lldb::thread_result_t()> impl)
+ : thread_name(std::move(thread_name)), impl(std::move(impl)) {}
};
};
}
void ResumePrivateStateThread();
private:
- struct PrivateStateThreadArgs {
- PrivateStateThreadArgs(Process *p, bool s)
- : process(p), is_secondary_thread(s){};
- Process *process;
- bool is_secondary_thread;
- };
-
- // arg is a pointer to a new'ed PrivateStateThreadArgs structure.
- // PrivateStateThread will free it for you.
- static lldb::thread_result_t PrivateStateThread(void *arg);
-
// The starts up the private state thread that will watch for events from the
// debugee. Pass true for is_secondary_thread in the case where you have to
// temporarily spin up a secondary state thread to handle events from a hand-
void *thread_arg, SBError *error_ptr) {
LLDB_INSTRUMENT_VA(name, thread_function, thread_arg, error_ptr);
llvm::Expected<HostThread> thread =
- ThreadLauncher::LaunchThread(name, thread_function, thread_arg);
+ ThreadLauncher::LaunchThread(name, [thread_function, thread_arg] {
+ return thread_function(thread_arg);
+ });
if (!thread) {
if (error_ptr)
error_ptr->SetError(Status(thread.takeError()));
m_read_thread_enabled = true;
m_read_thread_did_exit = false;
auto maybe_thread = ThreadLauncher::LaunchThread(
- thread_name, Communication::ReadThread, this);
+ thread_name, [this] { return ReadThread(); });
if (maybe_thread) {
m_read_thread = *maybe_thread;
} else {
bool Communication::ReadThreadIsRunning() { return m_read_thread_enabled; }
-lldb::thread_result_t Communication::ReadThread(lldb::thread_arg_t p) {
- Communication *comm = (Communication *)p;
-
+lldb::thread_result_t Communication::ReadThread() {
Log *log = GetLog(LLDBLog::Communication);
- LLDB_LOGF(log, "%p Communication::ReadThread () thread starting...", p);
+ LLDB_LOG(log, "Communication({0}) thread starting...", this);
uint8_t buf[1024];
ConnectionStatus status = eConnectionStatusSuccess;
bool done = false;
bool disconnect = false;
- while (!done && comm->m_read_thread_enabled) {
- size_t bytes_read = comm->ReadFromConnection(
+ while (!done && m_read_thread_enabled) {
+ size_t bytes_read = ReadFromConnection(
buf, sizeof(buf), std::chrono::seconds(5), status, &error);
if (bytes_read > 0 || status == eConnectionStatusEndOfFile)
- comm->AppendBytesToCache(buf, bytes_read, true, status);
+ AppendBytesToCache(buf, bytes_read, true, status);
switch (status) {
case eConnectionStatusSuccess:
case eConnectionStatusEndOfFile:
done = true;
- disconnect = comm->GetCloseOnEOF();
+ disconnect = GetCloseOnEOF();
break;
case eConnectionStatusError: // Check GetError() for details
if (error.GetType() == eErrorTypePOSIX && error.GetError() == EIO) {
// EIO on a pipe is usually caused by remote shutdown
- disconnect = comm->GetCloseOnEOF();
+ disconnect = GetCloseOnEOF();
done = true;
}
if (error.Fail())
// SynchronizeWithReadThread()
// The connection returns eConnectionStatusInterrupted only when there is
// no input pending to be read, so we can signal that.
- comm->BroadcastEvent(eBroadcastBitNoMorePendingInput);
+ BroadcastEvent(eBroadcastBitNoMorePendingInput);
break;
case eConnectionStatusNoConnection: // No connection
case eConnectionStatusLostConnection: // Lost connection while connected to
}
}
log = GetLog(LLDBLog::Communication);
- if (log)
- LLDB_LOGF(log, "%p Communication::ReadThread () thread exiting...", p);
+ LLDB_LOG(log, "Communication({0}) thread exiting...", this);
// Handle threads wishing to synchronize with us.
{
// Prevent new ones from showing up.
- comm->m_read_thread_did_exit = true;
+ m_read_thread_did_exit = true;
// Unblock any existing thread waiting for the synchronization signal.
- comm->BroadcastEvent(eBroadcastBitNoMorePendingInput);
+ BroadcastEvent(eBroadcastBitNoMorePendingInput);
// Wait for the thread to finish...
- std::lock_guard<std::mutex> guard(comm->m_synchronize_mutex);
+ std::lock_guard<std::mutex> guard(m_synchronize_mutex);
// ... and disconnect.
if (disconnect)
- comm->Disconnect();
+ Disconnect();
}
// Let clients know that this thread is exiting
- comm->BroadcastEvent(eBroadcastBitReadThreadDidExit);
+ BroadcastEvent(eBroadcastBitReadThreadDidExit);
return {};
}
m_forward_listener_sp.reset();
}
-void Debugger::DefaultEventHandler() {
+lldb::thread_result_t Debugger::DefaultEventHandler() {
ListenerSP listener_sp(GetListener());
ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());
ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
}
}
}
-}
-
-lldb::thread_result_t Debugger::EventHandlerThread(lldb::thread_arg_t arg) {
- ((Debugger *)arg)->DefaultEventHandler();
return {};
}
// Use larger 8MB stack for this thread
llvm::Expected<HostThread> event_handler_thread =
- ThreadLauncher::LaunchThread(thread_name, EventHandlerThread, this,
- g_debugger_event_thread_stack_bytes);
+ ThreadLauncher::LaunchThread(
+ thread_name, [this] { return DefaultEventHandler(); },
+ g_debugger_event_thread_stack_bytes);
if (event_handler_thread) {
m_event_handler_thread = *event_handler_thread;
}
}
-lldb::thread_result_t Debugger::IOHandlerThread(lldb::thread_arg_t arg) {
- Debugger *debugger = (Debugger *)arg;
- debugger->RunIOHandlers();
- debugger->StopEventHandlerThread();
+lldb::thread_result_t Debugger::IOHandlerThread() {
+ RunIOHandlers();
+ StopEventHandlerThread();
return {};
}
bool Debugger::StartIOHandlerThread() {
if (!m_io_handler_thread.IsJoinable()) {
llvm::Expected<HostThread> io_handler_thread = ThreadLauncher::LaunchThread(
- "lldb.debugger.io-handler", IOHandlerThread, this,
+ "lldb.debugger.io-handler", [this] { return IOHandlerThread(); },
8 * 1024 * 1024); // Use larger 8MB stack for this thread
if (io_handler_thread) {
m_io_handler_thread = *io_handler_thread;
using namespace lldb_private;
#if !defined(__APPLE__) && !defined(_WIN32)
-struct MonitorInfo {
- lldb::pid_t pid; // The process ID to monitor
- Host::MonitorChildProcessCallback
- callback; // The callback function to call when "pid" exits or signals
- bool monitor_signals; // If true, call the callback when "pid" gets signaled.
-};
-
-static thread_result_t MonitorChildProcessThreadFunction(void *arg);
+static thread_result_t
+MonitorChildProcessThreadFunction(::pid_t pid,
+ Host::MonitorChildProcessCallback callback,
+ bool monitor_signals);
llvm::Expected<HostThread> Host::StartMonitoringChildProcess(
const Host::MonitorChildProcessCallback &callback, lldb::pid_t pid,
bool monitor_signals) {
- MonitorInfo *info_ptr = new MonitorInfo();
-
- info_ptr->pid = pid;
- info_ptr->callback = callback;
- info_ptr->monitor_signals = monitor_signals;
-
char thread_name[256];
::snprintf(thread_name, sizeof(thread_name),
"<lldb.host.wait4(pid=%" PRIu64 ")>", pid);
- return ThreadLauncher::LaunchThread(
- thread_name, MonitorChildProcessThreadFunction, info_ptr, 0);
+ assert(pid <= UINT32_MAX);
+ return ThreadLauncher::LaunchThread(thread_name, [pid, callback,
+ monitor_signals] {
+ return MonitorChildProcessThreadFunction(pid, callback, monitor_signals);
+ });
}
#ifndef __linux__
return false;
}
-static thread_result_t MonitorChildProcessThreadFunction(void *arg) {
+static thread_result_t
+MonitorChildProcessThreadFunction(::pid_t pid,
+ Host::MonitorChildProcessCallback callback,
+ bool monitor_signals) {
Log *log = GetLog(LLDBLog::Process);
- const char *function = __FUNCTION__;
- LLDB_LOGF(log, "%s (arg = %p) thread starting...", function, arg);
-
- MonitorInfo *info = (MonitorInfo *)arg;
+ LLDB_LOG(log, "pid = {0}, monitor_signals = {1}", pid, monitor_signals);
- const Host::MonitorChildProcessCallback callback = info->callback;
- const bool monitor_signals = info->monitor_signals;
-
- assert(info->pid <= UINT32_MAX);
- const ::pid_t pid = monitor_signals ? -1 * getpgid(info->pid) : info->pid;
-
- delete info;
+ pid = monitor_signals ? -1 * getpgid(pid) : pid;
int status = -1;
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__)
while (true) {
log = GetLog(LLDBLog::Process);
- LLDB_LOGF(log, "%s ::waitpid (pid = %" PRIi32 ", &status, options = %i)...",
- function, pid, options);
+ LLDB_LOG(log, "::waitpid({0}, &status, {1})...", pid, options);
if (CheckForMonitorCancellation())
break;
continue;
else {
LLDB_LOG(log,
- "arg = {0}, thread exiting because waitpid failed ({1})...",
- arg, llvm::sys::StrError());
+ "pid = {0}, thread exiting because waitpid failed ({1})...",
+ pid, llvm::sys::StrError());
break;
}
} else if (wait_pid > 0) {
#endif
log = GetLog(LLDBLog::Process);
- LLDB_LOGF(log,
- "%s ::waitpid (pid = %" PRIi32
- ", &status, options = %i) => pid = %" PRIi32
- ", status = 0x%8.8x (%s), signal = %i, exit_state = %i",
- function, pid, options, wait_pid, status, status_cstr, signal,
- exit_status);
+ LLDB_LOG(log,
+ "::waitpid({0}, &status, {1}) => pid = {2}, status = {3:x} "
+ "({4}), signal = {5}, exit_state = {6}",
+ pid, options, wait_pid, status, status_cstr, signal,
+ exit_status);
if (exited || (signal != 0 && monitor_signals)) {
bool callback_return = false;
// If our process exited, then this thread should exit
if (exited && wait_pid == abs(pid)) {
- LLDB_LOGF(log,
- "%s (arg = %p) thread exiting because pid received "
- "exit signal...",
- __FUNCTION__, arg);
+ LLDB_LOG(
+ log,
+ "pid = {0} thread exiting because pid received exit signal...",
+ pid);
break;
}
// If the callback returns true, it means this process should exit
if (callback_return) {
- LLDB_LOGF(log,
- "%s (arg = %p) thread exiting because callback "
- "returned true...",
- __FUNCTION__, arg);
+ LLDB_LOG(
+ log,
+ "pid = {0} thread exiting because callback returned true...",
+ pid);
break;
}
}
}
}
- log = GetLog(LLDBLog::Process);
- LLDB_LOGF(log, "%s (arg = %p) thread exiting...", __FUNCTION__, arg);
-
+ LLDB_LOG(GetLog(LLDBLog::Process), "pid = {0} thread exiting...", pid);
return nullptr;
}
lldb::thread_result_t
HostNativeThreadBase::ThreadCreateTrampoline(lldb::thread_arg_t arg) {
- ThreadLauncher::HostThreadCreateInfo *info =
- (ThreadLauncher::HostThreadCreateInfo *)arg;
- llvm::set_thread_name(info->thread_name);
-
- thread_func_t thread_fptr = info->thread_fptr;
- thread_arg_t thread_arg = info->thread_arg;
+ std::unique_ptr<ThreadLauncher::HostThreadCreateInfo> info_up(
+ (ThreadLauncher::HostThreadCreateInfo *)arg);
+ llvm::set_thread_name(info_up->thread_name);
Log *log = GetLog(LLDBLog::Thread);
LLDB_LOGF(log, "thread created");
- delete info;
- return thread_fptr(thread_arg);
+ return info_up->impl();
}
using namespace lldb;
using namespace lldb_private;
-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);
+llvm::Expected<HostThread>
+ThreadLauncher::LaunchThread(llvm::StringRef name,
+ std::function<thread_result_t()> impl,
+ size_t min_stack_byte_size) {
+ // Host::ThreadCreateTrampoline will take ownership if thread creation is
+ // successful.
+ auto info_up = std::make_unique<HostThreadCreateInfo>(name.str(), impl);
lldb::thread_t thread;
#ifdef _WIN32
thread = (lldb::thread_t)::_beginthreadex(
0, (unsigned)min_stack_byte_size,
- HostNativeThread::ThreadCreateTrampoline, info_ptr, 0, NULL);
+ HostNativeThread::ThreadCreateTrampoline, info_up.get(), 0, NULL);
if (thread == LLDB_INVALID_HOST_THREAD)
return llvm::errorCodeToError(llvm::mapWindowsError(GetLastError()));
#else
}
int err =
::pthread_create(&thread, thread_attr_ptr,
- HostNativeThread::ThreadCreateTrampoline, info_ptr);
+ HostNativeThread::ThreadCreateTrampoline, info_up.get());
if (destroy_attr)
::pthread_attr_destroy(&thread_attr);
std::error_code(err, std::generic_category()));
#endif
+ info_up.release();
return HostThread(thread);
}
#if TARGET_OS_OSX
-static void *AcceptPIDFromInferior(void *arg) {
- const char *connect_url = (const char *)arg;
+static void *AcceptPIDFromInferior(const char *connect_url) {
ConnectionFileDescriptor file_conn;
Status error;
if (file_conn.Connect(connect_url, &error) == eConnectionStatusSuccess) {
// 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.
llvm::Expected<HostThread> accept_thread = ThreadLauncher::LaunchThread(
- unix_socket_name, AcceptPIDFromInferior, connect_url);
+ unix_socket_name, [&] { return AcceptPIDFromInferior(connect_url); });
if (!accept_thread)
return Status(accept_thread.takeError());
return true;
llvm::Expected<HostThread> async_thread = ThreadLauncher::LaunchThread(
- "<lldb.process.kdp-remote.async>", ProcessKDP::AsyncThread, this);
+ "<lldb.process.kdp-remote.async>", [this] { return AsyncThread(); });
if (!async_thread) {
LLDB_LOG_ERROR(GetLog(LLDBLog::Host), async_thread.takeError(),
"failed to launch host thread: {}");
m_async_thread.Join(nullptr);
}
-void *ProcessKDP::AsyncThread(void *arg) {
- ProcessKDP *process = (ProcessKDP *)arg;
-
- const lldb::pid_t pid = process->GetID();
+void *ProcessKDP::AsyncThread() {
+ const lldb::pid_t pid = GetID();
Log *log = GetLog(KDPLog::Process);
LLDB_LOGF(log,
- "ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64
- ") thread starting...",
- arg, pid);
+ "ProcessKDP::AsyncThread(pid = %" PRIu64 ") thread starting...",
+ pid);
ListenerSP listener_sp(Listener::MakeListener("ProcessKDP::AsyncThread"));
EventSP event_sp;
const uint32_t desired_event_mask =
eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit;
- if (listener_sp->StartListeningForEvents(&process->m_async_broadcaster,
- desired_event_mask) ==
- desired_event_mask) {
+ if (listener_sp->StartListeningForEvents(
+ &m_async_broadcaster, desired_event_mask) == desired_event_mask) {
bool done = false;
while (!done) {
LLDB_LOGF(log,
switch (event_type) {
case eBroadcastBitAsyncContinue: {
is_running = true;
- if (process->m_comm.WaitForPacketWithTimeoutMicroSeconds(
+ if (m_comm.WaitForPacketWithTimeoutMicroSeconds(
exc_reply_packet, 1 * USEC_PER_SEC)) {
- ThreadSP thread_sp(process->GetKernelThread());
+ ThreadSP thread_sp(GetKernelThread());
if (thread_sp) {
lldb::RegisterContextSP reg_ctx_sp(
thread_sp->GetRegisterContext());
// TODO: parse the stop reply packet
is_running = false;
- process->SetPrivateState(eStateStopped);
+ SetPrivateState(eStateStopped);
} else {
// Check to see if we are supposed to exit. There is no way to
// interrupt a running kernel, so all we can do is wait for an
}
}
- LLDB_LOGF(log,
- "ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64
- ") thread exiting...",
- arg, pid);
+ LLDB_LOGF(log, "ProcessKDP::AsyncThread(pid = %" PRIu64 ") thread exiting...",
+ pid);
- process->m_async_thread.Reset();
+ m_async_thread.Reset();
return NULL;
}
void StopAsyncThread();
- static void *AsyncThread(void *arg);
+ void *AsyncThread();
private:
// For ProcessKDP only
using namespace lldb;
using namespace lldb_private;
-namespace {
-struct DebugLaunchContext {
- DebugLaunchContext(DebuggerThread *thread,
- const ProcessLaunchInfo &launch_info)
- : m_thread(thread), m_launch_info(launch_info) {}
- DebuggerThread *m_thread;
- ProcessLaunchInfo m_launch_info;
-};
-
-struct DebugAttachContext {
- DebugAttachContext(DebuggerThread *thread, lldb::pid_t pid,
- const ProcessAttachInfo &attach_info)
- : m_thread(thread), m_pid(pid), m_attach_info(attach_info) {}
- DebuggerThread *m_thread;
- lldb::pid_t m_pid;
- ProcessAttachInfo m_attach_info;
-};
-} // namespace
-
DebuggerThread::DebuggerThread(DebugDelegateSP debug_delegate)
: m_debug_delegate(debug_delegate), m_pid_to_detach(0),
m_is_shutting_down(false) {
LLDB_LOG(log, "launching '{0}'", launch_info.GetExecutableFile().GetPath());
Status result;
- DebugLaunchContext *context = new DebugLaunchContext(this, launch_info);
-
- llvm::Expected<HostThread> secondary_thread =
- ThreadLauncher::LaunchThread("lldb.plugin.process-windows.secondary[?]",
- DebuggerThreadLaunchRoutine, context);
+ llvm::Expected<HostThread> secondary_thread = ThreadLauncher::LaunchThread(
+ "lldb.plugin.process-windows.secondary[?]",
+ [this, launch_info] { return DebuggerThreadLaunchRoutine(launch_info); });
if (!secondary_thread) {
result = Status(secondary_thread.takeError());
LLDB_LOG(log, "couldn't launch debugger thread. {0}", result);
LLDB_LOG(log, "attaching to '{0}'", pid);
Status result;
- DebugAttachContext *context = new DebugAttachContext(this, pid, attach_info);
-
- llvm::Expected<HostThread> secondary_thread =
- ThreadLauncher::LaunchThread("lldb.plugin.process-windows.secondary[?]",
- DebuggerThreadAttachRoutine, context);
+ llvm::Expected<HostThread> secondary_thread = ThreadLauncher::LaunchThread(
+ "lldb.plugin.process-windows.secondary[?]", [this, pid, attach_info] {
+ return DebuggerThreadAttachRoutine(pid, attach_info);
+ });
if (!secondary_thread) {
result = Status(secondary_thread.takeError());
LLDB_LOG(log, "couldn't attach to process '{0}'. {1}", pid, result);
return result;
}
-lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine(void *data) {
- DebugLaunchContext *context = static_cast<DebugLaunchContext *>(data);
- lldb::thread_result_t result =
- context->m_thread->DebuggerThreadLaunchRoutine(context->m_launch_info);
- delete context;
- return result;
-}
-
-lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine(void *data) {
- DebugAttachContext *context = static_cast<DebugAttachContext *>(data);
- lldb::thread_result_t result = context->m_thread->DebuggerThreadAttachRoutine(
- context->m_pid, context->m_attach_info);
- delete context;
- return result;
-}
-
lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine(
const ProcessLaunchInfo &launch_info) {
// Grab a shared_ptr reference to this so that we know it won't get deleted
// exit.
bool m_detached = false;
- static lldb::thread_result_t DebuggerThreadLaunchRoutine(void *data);
lldb::thread_result_t
DebuggerThreadLaunchRoutine(const ProcessLaunchInfo &launch_info);
- static lldb::thread_result_t DebuggerThreadAttachRoutine(void *data);
lldb::thread_result_t
DebuggerThreadAttachRoutine(lldb::pid_t pid,
const ProcessAttachInfo &launch_info);
m_listen_url = listen_url;
SetConnection(std::make_unique<ConnectionFileDescriptor>());
llvm::Expected<HostThread> listen_thread = ThreadLauncher::LaunchThread(
- listen_url, GDBRemoteCommunication::ListenThread, this);
+ listen_url, [this] { return GDBRemoteCommunication::ListenThread(); });
if (!listen_thread)
return Status(listen_thread.takeError());
m_listen_thread = *listen_thread;
return true;
}
-lldb::thread_result_t
-GDBRemoteCommunication::ListenThread(lldb::thread_arg_t arg) {
- GDBRemoteCommunication *comm = (GDBRemoteCommunication *)arg;
+lldb::thread_result_t GDBRemoteCommunication::ListenThread() {
Status error;
ConnectionFileDescriptor *connection =
- (ConnectionFileDescriptor *)comm->GetConnection();
+ (ConnectionFileDescriptor *)GetConnection();
if (connection) {
// Do the listen on another thread so we can continue on...
if (connection->Connect(
- comm->m_listen_url.c_str(), [comm](llvm::StringRef port_str) {
+ m_listen_url.c_str(),
+ [this](llvm::StringRef port_str) {
uint16_t port = 0;
llvm::to_integer(port_str, port, 10);
- comm->m_port_promise.set_value(port);
+ m_port_promise.set_value(port);
},
&error) != eConnectionStatusSuccess)
- comm->SetConnection(nullptr);
+ SetConnection(nullptr);
}
return {};
}
bool JoinListenThread();
- static lldb::thread_result_t ListenThread(lldb::thread_arg_t arg);
+ lldb::thread_result_t ListenThread();
private:
// Promise used to grab the port number from listening thread
// Create a thread that watches our internal state and controls which
// events make it to clients (into the DCProcess event queue).
- llvm::Expected<HostThread> async_thread = ThreadLauncher::LaunchThread(
- "<lldb.process.gdb-remote.async>", ProcessGDBRemote::AsyncThread, this);
+ llvm::Expected<HostThread> async_thread =
+ ThreadLauncher::LaunchThread("<lldb.process.gdb-remote.async>", [this] {
+ return ProcessGDBRemote::AsyncThread();
+ });
if (!async_thread) {
LLDB_LOG_ERROR(GetLog(LLDBLog::Host), async_thread.takeError(),
"failed to launch host thread: {}");
__FUNCTION__);
}
-thread_result_t ProcessGDBRemote::AsyncThread(void *arg) {
- ProcessGDBRemote *process = (ProcessGDBRemote *)arg;
-
+thread_result_t ProcessGDBRemote::AsyncThread() {
Log *log = GetLog(GDBRLog::Process);
- LLDB_LOGF(log,
- "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
- ") thread starting...",
- __FUNCTION__, arg, process->GetID());
+ LLDB_LOGF(log, "ProcessGDBRemote::%s(pid = %" PRIu64 ") thread starting...",
+ __FUNCTION__, GetID());
EventSP event_sp;
// fetch loop.
bool done = false;
- while (!done && process->GetPrivateState() != eStateExited) {
+ while (!done && GetPrivateState() != eStateExited) {
LLDB_LOGF(log,
- "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ "ProcessGDBRemote::%s(pid = %" PRIu64
") listener.WaitForEvent (NULL, event_sp)...",
- __FUNCTION__, arg, process->GetID());
+ __FUNCTION__, GetID());
- if (process->m_async_listener_sp->GetEvent(event_sp, llvm::None)) {
+ if (m_async_listener_sp->GetEvent(event_sp, llvm::None)) {
const uint32_t event_type = event_sp->GetType();
- if (event_sp->BroadcasterIs(&process->m_async_broadcaster)) {
+ if (event_sp->BroadcasterIs(&m_async_broadcaster)) {
LLDB_LOGF(log,
- "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ "ProcessGDBRemote::%s(pid = %" PRIu64
") Got an event of type: %d...",
- __FUNCTION__, arg, process->GetID(), event_type);
+ __FUNCTION__, GetID(), event_type);
switch (event_type) {
case eBroadcastBitAsyncContinue: {
(const char *)continue_packet->GetBytes();
const size_t continue_cstr_len = continue_packet->GetByteSize();
LLDB_LOGF(log,
- "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ "ProcessGDBRemote::%s(pid = %" PRIu64
") got eBroadcastBitAsyncContinue: %s",
- __FUNCTION__, arg, process->GetID(), continue_cstr);
+ __FUNCTION__, GetID(), continue_cstr);
if (::strstr(continue_cstr, "vAttach") == nullptr)
- process->SetPrivateState(eStateRunning);
+ SetPrivateState(eStateRunning);
StringExtractorGDBRemote response;
StateType stop_state =
- process->GetGDBRemote().SendContinuePacketAndWaitForResponse(
- *process, *process->GetUnixSignals(),
+ GetGDBRemote().SendContinuePacketAndWaitForResponse(
+ *this, *GetUnixSignals(),
llvm::StringRef(continue_cstr, continue_cstr_len),
- process->GetInterruptTimeout(), response);
+ GetInterruptTimeout(), response);
// We need to immediately clear the thread ID list so we are sure
// to get a valid list of threads. The thread ID list might be
// contained within the "response", or the stop reply packet that
// caused the stop. So clear it now before we give the stop reply
// packet to the process using the
- // process->SetLastStopPacket()...
- process->ClearThreadIDList();
+ // SetLastStopPacket()...
+ ClearThreadIDList();
switch (stop_state) {
case eStateStopped:
case eStateCrashed:
case eStateSuspended:
- process->SetLastStopPacket(response);
- process->SetPrivateState(stop_state);
+ SetLastStopPacket(response);
+ SetPrivateState(stop_state);
break;
case eStateExited: {
- process->SetLastStopPacket(response);
- process->ClearThreadIDList();
+ SetLastStopPacket(response);
+ ClearThreadIDList();
response.SetFilePos(1);
int exit_status = response.GetHexU8();
extractor.GetHexByteString(desc_string);
}
}
- process->SetExitStatus(exit_status, desc_string.c_str());
+ SetExitStatus(exit_status, desc_string.c_str());
done = true;
break;
}
// helpful error message about why the attach failed.
if (::strstr(continue_cstr, "vAttach") != nullptr &&
response.GetError() == 0x87) {
- process->SetExitStatus(-1, "cannot attach to process due to "
- "System Integrity Protection");
+ SetExitStatus(-1, "cannot attach to process due to "
+ "System Integrity Protection");
} else if (::strstr(continue_cstr, "vAttach") != nullptr &&
response.GetStatus().Fail()) {
- process->SetExitStatus(-1, response.GetStatus().AsCString());
+ SetExitStatus(-1, response.GetStatus().AsCString());
} else {
- process->SetExitStatus(-1, "lost connection");
+ SetExitStatus(-1, "lost connection");
}
done = true;
break;
}
default:
- process->SetPrivateState(stop_state);
+ SetPrivateState(stop_state);
break;
} // switch(stop_state)
} // if (continue_packet)
case eBroadcastBitAsyncThreadShouldExit:
LLDB_LOGF(log,
- "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ "ProcessGDBRemote::%s(pid = %" PRIu64
") got eBroadcastBitAsyncThreadShouldExit...",
- __FUNCTION__, arg, process->GetID());
+ __FUNCTION__, GetID());
done = true;
break;
default:
LLDB_LOGF(log,
- "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ "ProcessGDBRemote::%s(pid = %" PRIu64
") got unknown event 0x%8.8x",
- __FUNCTION__, arg, process->GetID(), event_type);
+ __FUNCTION__, GetID(), event_type);
done = true;
break;
}
- } else if (event_sp->BroadcasterIs(&process->m_gdb_comm)) {
+ } else if (event_sp->BroadcasterIs(&m_gdb_comm)) {
switch (event_type) {
case Communication::eBroadcastBitReadThreadDidExit:
- process->SetExitStatus(-1, "lost connection");
+ SetExitStatus(-1, "lost connection");
done = true;
break;
default:
LLDB_LOGF(log,
- "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ "ProcessGDBRemote::%s(pid = %" PRIu64
") got unknown event 0x%8.8x",
- __FUNCTION__, arg, process->GetID(), event_type);
+ __FUNCTION__, GetID(), event_type);
done = true;
break;
}
}
} else {
LLDB_LOGF(log,
- "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ "ProcessGDBRemote::%s(pid = %" PRIu64
") listener.WaitForEvent (NULL, event_sp) => false",
- __FUNCTION__, arg, process->GetID());
+ __FUNCTION__, GetID());
done = true;
}
}
- LLDB_LOGF(log,
- "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
- ") thread exiting...",
- __FUNCTION__, arg, process->GetID());
+ LLDB_LOGF(log, "ProcessGDBRemote::%s(pid = %" PRIu64 ") thread exiting...",
+ __FUNCTION__, GetID());
return {};
}
void StopAsyncThread();
- static lldb::thread_result_t AsyncThread(void *arg);
+ lldb::thread_result_t AsyncThread();
static bool
MonitorDebugserverProcess(std::weak_ptr<ProcessGDBRemote> process_wp,
"<lldb.process.internal-state(pid=%" PRIu64 ")>", GetID());
}
- // Create the private state thread, and start it running.
- PrivateStateThreadArgs *args_ptr =
- new PrivateStateThreadArgs(this, is_secondary_thread);
llvm::Expected<HostThread> private_state_thread =
- ThreadLauncher::LaunchThread(thread_name, Process::PrivateStateThread,
- (void *)args_ptr, 8 * 1024 * 1024);
+ ThreadLauncher::LaunchThread(
+ thread_name,
+ [this, is_secondary_thread] {
+ return RunPrivateStateThread(is_secondary_thread);
+ },
+ 8 * 1024 * 1024);
if (!private_state_thread) {
LLDB_LOG(GetLog(LLDBLog::Host), "failed to launch host thread: {}",
llvm::toString(private_state_thread.takeError()));
return error;
}
-thread_result_t Process::PrivateStateThread(void *arg) {
- std::unique_ptr<PrivateStateThreadArgs> args_up(
- static_cast<PrivateStateThreadArgs *>(arg));
- thread_result_t result =
- args_up->process->RunPrivateStateThread(args_up->is_secondary_thread);
- return result;
-}
-
thread_result_t Process::RunPrivateStateThread(bool is_secondary_thread) {
bool control_only = true;
SocketAddressTest.cpp
SocketTest.cpp
SocketTestUtilities.cpp
+ ThreadLauncherTest.cpp
XMLTest.cpp
)
--- /dev/null
+//===-- ThreadLauncherTest.cpp --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Host/ThreadLauncher.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gtest/gtest.h"
+#include <future>
+
+using namespace lldb_private;
+
+TEST(ThreadLauncherTest, LaunchThread) {
+ std::promise<int> promise;
+ std::future<int> future = promise.get_future();
+ llvm::Expected<HostThread> thread =
+ ThreadLauncher::LaunchThread("test", [&promise] {
+ promise.set_value(47);
+ return (lldb::thread_result_t)47;
+ });
+ ASSERT_THAT_EXPECTED(thread, llvm::Succeeded());
+ EXPECT_EQ(future.get(), 47);
+ lldb::thread_result_t result;
+ thread->Join(&result);
+ EXPECT_EQ(result, (lldb::thread_result_t)47);
+}