diff --git a/lldb/include/lldb/Core/Communication.h b/lldb/include/lldb/Core/Communication.h --- a/lldb/include/lldb/Core/Communication.h +++ b/lldb/include/lldb/Core/Communication.h @@ -277,7 +277,7 @@ /// \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. @@ -289,7 +289,7 @@ /// \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); diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h --- a/lldb/include/lldb/Core/Debugger.h +++ b/lldb/include/lldb/Core/Debugger.h @@ -439,8 +439,6 @@ 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); @@ -454,9 +452,9 @@ 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); diff --git a/lldb/include/lldb/Host/ThreadLauncher.h b/lldb/include/lldb/Host/ThreadLauncher.h --- a/lldb/include/lldb/Host/ThreadLauncher.h +++ b/lldb/include/lldb/Host/ThreadLauncher.h @@ -20,8 +20,8 @@ class ThreadLauncher { public: static llvm::Expected - LaunchThread(llvm::StringRef name, lldb::thread_func_t thread_function, - lldb::thread_arg_t thread_arg, + LaunchThread(llvm::StringRef name, + std::function thread_function, size_t min_stack_byte_size = 0); // Minimum stack size in bytes, // set stack size to zero for // default platform thread stack @@ -29,12 +29,11 @@ struct HostThreadCreateInfo { std::string thread_name; - lldb::thread_func_t thread_fptr; - lldb::thread_arg_t thread_arg; + std::function 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 impl) + : thread_name(std::move(thread_name)), impl(std::move(impl)) {} }; }; } diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -2989,17 +2989,6 @@ 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- diff --git a/lldb/source/API/SBHostOS.cpp b/lldb/source/API/SBHostOS.cpp --- a/lldb/source/API/SBHostOS.cpp +++ b/lldb/source/API/SBHostOS.cpp @@ -102,7 +102,9 @@ void *thread_arg, SBError *error_ptr) { LLDB_INSTRUMENT_VA(name, thread_function, thread_arg, error_ptr); llvm::Expected 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())); diff --git a/lldb/source/Core/Communication.cpp b/lldb/source/Core/Communication.cpp --- a/lldb/source/Core/Communication.cpp +++ b/lldb/source/Core/Communication.cpp @@ -213,7 +213,7 @@ 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 { @@ -311,12 +311,10 @@ 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]; @@ -324,11 +322,11 @@ 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: @@ -336,12 +334,12 @@ 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()) @@ -352,7 +350,7 @@ // 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 @@ -367,26 +365,25 @@ } } 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 guard(comm->m_synchronize_mutex); + std::lock_guard 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 {}; } diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -1576,7 +1576,7 @@ 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()); @@ -1662,10 +1662,6 @@ } } } -} - -lldb::thread_result_t Debugger::EventHandlerThread(lldb::thread_arg_t arg) { - ((Debugger *)arg)->DefaultEventHandler(); return {}; } @@ -1687,8 +1683,9 @@ // Use larger 8MB stack for this thread llvm::Expected 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; @@ -1716,10 +1713,9 @@ } } -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 {}; } @@ -1728,7 +1724,7 @@ bool Debugger::StartIOHandlerThread() { if (!m_io_handler_thread.IsJoinable()) { llvm::Expected 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; diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp --- a/lldb/source/Host/common/Host.cpp +++ b/lldb/source/Host/common/Host.cpp @@ -92,29 +92,22 @@ 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 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), "", 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__ @@ -163,20 +156,14 @@ 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__) @@ -194,8 +181,7 @@ 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; @@ -211,8 +197,8 @@ 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) { @@ -245,12 +231,11 @@ #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; @@ -259,18 +244,18 @@ // 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; } } @@ -278,9 +263,7 @@ } } - 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; } diff --git a/lldb/source/Host/common/HostNativeThreadBase.cpp b/lldb/source/Host/common/HostNativeThreadBase.cpp --- a/lldb/source/Host/common/HostNativeThreadBase.cpp +++ b/lldb/source/Host/common/HostNativeThreadBase.cpp @@ -52,16 +52,12 @@ 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 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(); } diff --git a/lldb/source/Host/common/ThreadLauncher.cpp b/lldb/source/Host/common/ThreadLauncher.cpp --- a/lldb/source/Host/common/ThreadLauncher.cpp +++ b/lldb/source/Host/common/ThreadLauncher.cpp @@ -21,17 +21,18 @@ using namespace lldb; using namespace lldb_private; -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); +llvm::Expected +ThreadLauncher::LaunchThread(llvm::StringRef name, + std::function impl, + size_t min_stack_byte_size) { + // Host::ThreadCreateTrampoline will take ownership if thread creation is + // successful. + auto info_up = std::make_unique(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 @@ -63,7 +64,7 @@ } 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); @@ -73,5 +74,6 @@ std::error_code(err, std::generic_category())); #endif + info_up.release(); return HostThread(thread); } diff --git a/lldb/source/Host/macosx/objcxx/Host.mm b/lldb/source/Host/macosx/objcxx/Host.mm --- a/lldb/source/Host/macosx/objcxx/Host.mm +++ b/lldb/source/Host/macosx/objcxx/Host.mm @@ -136,8 +136,7 @@ #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) { @@ -286,7 +285,7 @@ // 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 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()); diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h @@ -179,7 +179,7 @@ void StopAsyncThread(); - static void *AsyncThread(void *arg); + void *AsyncThread(); private: // For ProcessKDP only diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp @@ -724,7 +724,7 @@ return true; llvm::Expected async_thread = ThreadLauncher::LaunchThread( - "", ProcessKDP::AsyncThread, this); + "", [this] { return AsyncThread(); }); if (!async_thread) { LLDB_LOG_ERROR(GetLog(LLDBLog::Host), async_thread.takeError(), "failed to launch host thread: {}"); @@ -746,25 +746,21 @@ 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, @@ -787,9 +783,9 @@ 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()); @@ -801,7 +797,7 @@ // 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 @@ -843,12 +839,10 @@ } } - 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; } diff --git a/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.h b/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.h --- a/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.h +++ b/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.h @@ -91,10 +91,8 @@ // 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); diff --git a/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp b/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp --- a/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp @@ -36,25 +36,6 @@ 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) { @@ -68,11 +49,9 @@ LLDB_LOG(log, "launching '{0}'", launch_info.GetExecutableFile().GetPath()); Status result; - DebugLaunchContext *context = new DebugLaunchContext(this, launch_info); - - llvm::Expected secondary_thread = - ThreadLauncher::LaunchThread("lldb.plugin.process-windows.secondary[?]", - DebuggerThreadLaunchRoutine, context); + llvm::Expected 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); @@ -87,11 +66,10 @@ LLDB_LOG(log, "attaching to '{0}'", pid); Status result; - DebugAttachContext *context = new DebugAttachContext(this, pid, attach_info); - - llvm::Expected secondary_thread = - ThreadLauncher::LaunchThread("lldb.plugin.process-windows.secondary[?]", - DebuggerThreadAttachRoutine, context); + llvm::Expected 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); @@ -100,22 +78,6 @@ return result; } -lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine(void *data) { - DebugLaunchContext *context = static_cast(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(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 diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -218,7 +218,7 @@ 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 diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -843,7 +843,7 @@ m_listen_url = listen_url; SetConnection(std::make_unique()); llvm::Expected 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; @@ -857,23 +857,22 @@ 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 {}; } diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -342,7 +342,7 @@ void StopAsyncThread(); - static lldb::thread_result_t AsyncThread(void *arg); + lldb::thread_result_t AsyncThread(); static bool MonitorDebugserverProcess(std::weak_ptr process_wp, diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -3541,8 +3541,10 @@ // Create a thread that watches our internal state and controls which // events make it to clients (into the DCProcess event queue). - llvm::Expected async_thread = ThreadLauncher::LaunchThread( - "", ProcessGDBRemote::AsyncThread, this); + llvm::Expected async_thread = + ThreadLauncher::LaunchThread("", [this] { + return ProcessGDBRemote::AsyncThread(); + }); if (!async_thread) { LLDB_LOG_ERROR(GetLog(LLDBLog::Host), async_thread.takeError(), "failed to launch host thread: {}"); @@ -3580,14 +3582,10 @@ __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; @@ -3603,19 +3601,19 @@ // 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: { @@ -3627,39 +3625,39 @@ (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(); @@ -3674,7 +3672,7 @@ extractor.GetHexByteString(desc_string); } } - process->SetExitStatus(exit_status, desc_string.c_str()); + SetExitStatus(exit_status, desc_string.c_str()); done = true; break; } @@ -3685,20 +3683,20 @@ // 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) @@ -3707,49 +3705,47 @@ 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 {}; } diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -3509,12 +3509,13 @@ "", GetID()); } - // Create the private state thread, and start it running. - PrivateStateThreadArgs *args_ptr = - new PrivateStateThreadArgs(this, is_secondary_thread); llvm::Expected 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())); @@ -3729,14 +3730,6 @@ return error; } -thread_result_t Process::PrivateStateThread(void *arg) { - std::unique_ptr args_up( - static_cast(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; diff --git a/lldb/unittests/Host/CMakeLists.txt b/lldb/unittests/Host/CMakeLists.txt --- a/lldb/unittests/Host/CMakeLists.txt +++ b/lldb/unittests/Host/CMakeLists.txt @@ -12,6 +12,7 @@ SocketAddressTest.cpp SocketTest.cpp SocketTestUtilities.cpp + ThreadLauncherTest.cpp XMLTest.cpp ) diff --git a/lldb/unittests/Host/ThreadLauncherTest.cpp b/lldb/unittests/Host/ThreadLauncherTest.cpp new file mode 100644 --- /dev/null +++ b/lldb/unittests/Host/ThreadLauncherTest.cpp @@ -0,0 +1,29 @@ +//===-- 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 + +using namespace lldb_private; + +TEST(ThreadLauncherTest, LaunchThread) { + std::promise promise; + std::future future = promise.get_future(); + llvm::Expected 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); +}