From a784a68ece20755b79bb87839673ff9cac2db69f Mon Sep 17 00:00:00 2001 From: qxy11 Date: Mon, 25 Aug 2025 16:26:17 -0700 Subject: [PATCH 1/4] Fix GPU process to exit when native process exits --- .../gdb-remote/GDBRemoteCommunicationServerLLGS.cpp | 8 ++++++++ .../source/Plugins/Process/gdb-remote/LLDBServerPlugin.h | 8 ++++++++ .../Plugins/MockGPU/LLDBServerPluginMockGPU.cpp | 9 +++++++++ .../Plugins/MockGPU/LLDBServerPluginMockGPU.h | 1 + .../tools/lldb-server/Plugins/MockGPU/ProcessMockGPU.cpp | 9 +++++++++ lldb/tools/lldb-server/Plugins/MockGPU/ProcessMockGPU.h | 3 +++ 6 files changed, 38 insertions(+) diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 4bc3c31ea80c3..ccde1a6f7bb52 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -1140,6 +1140,14 @@ void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited( Log *log = GetLog(LLDBLog::Process); LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); + // Notify GPU plugins that the native process has exited + auto exit_status = process->GetExitStatus(); + if (exit_status.has_value()) { + for (auto &plugin_up : m_plugins) { + plugin_up->NativeProcessDidExit(*exit_status); + } + } + PacketResult result = SendStopReasonForState( *process, StateType::eStateExited, /*force_synchronous=*/false); if (result != PacketResult::Success) { diff --git a/lldb/source/Plugins/Process/gdb-remote/LLDBServerPlugin.h b/lldb/source/Plugins/Process/gdb-remote/LLDBServerPlugin.h index a5c98ce26c177..0d8a35a6df633 100644 --- a/lldb/source/Plugins/Process/gdb-remote/LLDBServerPlugin.h +++ b/lldb/source/Plugins/Process/gdb-remote/LLDBServerPlugin.h @@ -82,6 +82,14 @@ class LLDBServerPlugin { return std::nullopt; }; + /// Get the GPU plug-in notified when the native process exits. + /// + /// This function will get called when the native process exits. This allows + /// GPU plugins to perform proper termination + /// + /// \param[in] exit_status The exit status of the native process. + virtual void NativeProcessDidExit(const WaitStatus &exit_status) {}; + /// Get the GPU plug-in initialization actions. /// /// Each GPU plugin can return a structure that describes the GPU plug-in and diff --git a/lldb/tools/lldb-server/Plugins/MockGPU/LLDBServerPluginMockGPU.cpp b/lldb/tools/lldb-server/Plugins/MockGPU/LLDBServerPluginMockGPU.cpp index c781e071f94d9..5c69fdbeebb30 100644 --- a/lldb/tools/lldb-server/Plugins/MockGPU/LLDBServerPluginMockGPU.cpp +++ b/lldb/tools/lldb-server/Plugins/MockGPU/LLDBServerPluginMockGPU.cpp @@ -164,6 +164,15 @@ std::optional LLDBServerPluginMockGPU::NativeProcessIsStopping() { return std::nullopt; } +void LLDBServerPluginMockGPU::NativeProcessDidExit( + const WaitStatus &exit_status) { + // Tell the GPU process to exit + NativeProcessProtocol *gpu_process = m_gdb_server->GetCurrentProcess(); + if (auto *mock_gpu_process = static_cast(gpu_process)) { + mock_gpu_process->HandleNativeProcessExit(exit_status); + } +} + llvm::Expected LLDBServerPluginMockGPU::BreakpointWasHit(GPUPluginBreakpointHitArgs &args) { const auto bp_identifier = args.breakpoint.identifier; diff --git a/lldb/tools/lldb-server/Plugins/MockGPU/LLDBServerPluginMockGPU.h b/lldb/tools/lldb-server/Plugins/MockGPU/LLDBServerPluginMockGPU.h index 6c52830e911d7..b481ece2a2aa8 100644 --- a/lldb/tools/lldb-server/Plugins/MockGPU/LLDBServerPluginMockGPU.h +++ b/lldb/tools/lldb-server/Plugins/MockGPU/LLDBServerPluginMockGPU.h @@ -80,6 +80,7 @@ class LLDBServerPluginMockGPU : public LLDBServerPlugin { bool HandleEventFileDescriptorEvent(int fd) override; GPUActions GetInitializeActions() override; std::optional NativeProcessIsStopping() override; + void NativeProcessDidExit(const WaitStatus &exit_status) override; llvm::Expected BreakpointWasHit(GPUPluginBreakpointHitArgs &args) override; diff --git a/lldb/tools/lldb-server/Plugins/MockGPU/ProcessMockGPU.cpp b/lldb/tools/lldb-server/Plugins/MockGPU/ProcessMockGPU.cpp index c1e984ff47c18..a37fe619c72af 100644 --- a/lldb/tools/lldb-server/Plugins/MockGPU/ProcessMockGPU.cpp +++ b/lldb/tools/lldb-server/Plugins/MockGPU/ProcessMockGPU.cpp @@ -249,3 +249,12 @@ ProcessMockGPU::Extension ProcessMockGPU::Manager::GetSupportedExtensions() const { return Extension::gpu_dyld | Extension::address_spaces; } + +void ProcessMockGPU::HandleNativeProcessExit(const WaitStatus &exit_status) { + Log *log = GetLog(GDBRLog::Plugin); + LLDB_LOG(log, "ProcessMockGPU::{0}() native process exited with status=({1})", + __FUNCTION__, exit_status); + + // Set our exit status to match the native process and notify delegates + SetExitStatus(exit_status, true); +} diff --git a/lldb/tools/lldb-server/Plugins/MockGPU/ProcessMockGPU.h b/lldb/tools/lldb-server/Plugins/MockGPU/ProcessMockGPU.h index 32111f2e6e857..9e5e38c931040 100644 --- a/lldb/tools/lldb-server/Plugins/MockGPU/ProcessMockGPU.h +++ b/lldb/tools/lldb-server/Plugins/MockGPU/ProcessMockGPU.h @@ -105,6 +105,9 @@ class Manager : public NativeProcessProtocol::Manager { // Custom accessors void SetLaunchInfo(ProcessLaunchInfo &launch_info); + + /// Called when the native process exits to set the GPU process exit status + void HandleNativeProcessExit(const WaitStatus &exit_status); }; From 0ccdd79b80bcb8f1a8029744cf31b2e7ee0b55f6 Mon Sep 17 00:00:00 2001 From: Janet Yang Date: Thu, 28 Aug 2025 09:56:53 -0700 Subject: [PATCH 2/4] Address lints, make exit calls pure virtual, add bare bones AMD implementation --- lldb/include/lldb/Host/common/NativeProcessProtocol.h | 3 ++- .../gdb-remote/GDBRemoteCommunicationServerLLGS.cpp | 5 ++--- lldb/source/Plugins/Process/gdb-remote/LLDBServerPlugin.h | 4 ++-- .../lldb-server/Plugins/AMDGPU/LLDBServerPluginAMDGPU.cpp | 7 +++++++ .../lldb-server/Plugins/AMDGPU/LLDBServerPluginAMDGPU.h | 1 + lldb/tools/lldb-server/Plugins/AMDGPU/ProcessAMDGPU.cpp | 5 +++++ lldb/tools/lldb-server/Plugins/AMDGPU/ProcessAMDGPU.h | 3 +++ .../Plugins/MockGPU/LLDBServerPluginMockGPU.cpp | 3 +-- lldb/tools/lldb-server/Plugins/MockGPU/ProcessMockGPU.h | 2 +- 9 files changed, 24 insertions(+), 9 deletions(-) diff --git a/lldb/include/lldb/Host/common/NativeProcessProtocol.h b/lldb/include/lldb/Host/common/NativeProcessProtocol.h index 5ef9f14c5ab3c..f8422eed409f8 100644 --- a/lldb/include/lldb/Host/common/NativeProcessProtocol.h +++ b/lldb/include/lldb/Host/common/NativeProcessProtocol.h @@ -301,7 +301,8 @@ class NativeProcessProtocol { return std::nullopt; }; - + // Handle exiting the GPU process when a native process exits. + virtual void HandleNativeProcessExit(const WaitStatus &exit_status) {}; /// Extension flag constants, returned by Manager::GetSupportedExtensions() /// and passed to SetEnabledExtension() diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index ccde1a6f7bb52..29b285dd28de0 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -1141,12 +1141,11 @@ void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited( LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); // Notify GPU plugins that the native process has exited - auto exit_status = process->GetExitStatus(); - if (exit_status.has_value()) { + std::optional exit_status = process->GetExitStatus(); + if (exit_status.has_value()) for (auto &plugin_up : m_plugins) { plugin_up->NativeProcessDidExit(*exit_status); } - } PacketResult result = SendStopReasonForState( *process, StateType::eStateExited, /*force_synchronous=*/false); diff --git a/lldb/source/Plugins/Process/gdb-remote/LLDBServerPlugin.h b/lldb/source/Plugins/Process/gdb-remote/LLDBServerPlugin.h index 0d8a35a6df633..8a692f0ffe59e 100644 --- a/lldb/source/Plugins/Process/gdb-remote/LLDBServerPlugin.h +++ b/lldb/source/Plugins/Process/gdb-remote/LLDBServerPlugin.h @@ -85,10 +85,10 @@ class LLDBServerPlugin { /// Get the GPU plug-in notified when the native process exits. /// /// This function will get called when the native process exits. This allows - /// GPU plugins to perform proper termination + /// GPU plugins to perform proper termination. /// /// \param[in] exit_status The exit status of the native process. - virtual void NativeProcessDidExit(const WaitStatus &exit_status) {}; + virtual void NativeProcessDidExit(const WaitStatus &exit_status) = 0; /// Get the GPU plug-in initialization actions. /// diff --git a/lldb/tools/lldb-server/Plugins/AMDGPU/LLDBServerPluginAMDGPU.cpp b/lldb/tools/lldb-server/Plugins/AMDGPU/LLDBServerPluginAMDGPU.cpp index d94bb0b712e37..5cb44f1b2e0a8 100644 --- a/lldb/tools/lldb-server/Plugins/AMDGPU/LLDBServerPluginAMDGPU.cpp +++ b/lldb/tools/lldb-server/Plugins/AMDGPU/LLDBServerPluginAMDGPU.cpp @@ -562,6 +562,13 @@ LLDBServerPluginAMDGPU::BreakpointWasHit(GPUPluginBreakpointHitArgs &args) { return response; } +void LLDBServerPluginAMDGPU::NativeProcessDidExit(const WaitStatus &exit_status) { + // Bare bones implementation for exit behavior if GPU process exits. + ProcessAMDGPU *gpu_process = GetGPUProcess(); + if (gpu_process) + gpu_process->HandleNativeProcessExit(exit_status); +} + GPUActions LLDBServerPluginAMDGPU::GetInitializeActions() { GPUActions init_actions; init_actions.plugin_name = GetPluginName(); diff --git a/lldb/tools/lldb-server/Plugins/AMDGPU/LLDBServerPluginAMDGPU.h b/lldb/tools/lldb-server/Plugins/AMDGPU/LLDBServerPluginAMDGPU.h index 134b4518b5da3..7ecbfd732a126 100644 --- a/lldb/tools/lldb-server/Plugins/AMDGPU/LLDBServerPluginAMDGPU.h +++ b/lldb/tools/lldb-server/Plugins/AMDGPU/LLDBServerPluginAMDGPU.h @@ -56,6 +56,7 @@ class LLDBServerPluginAMDGPU : public LLDBServerPlugin { bool HandleEventFileDescriptorEvent(int fd) override; GPUActions GetInitializeActions() override; std::optional NativeProcessIsStopping() override; + void NativeProcessDidExit(const WaitStatus &exit_status) override; llvm::Expected BreakpointWasHit(GPUPluginBreakpointHitArgs &args) override; diff --git a/lldb/tools/lldb-server/Plugins/AMDGPU/ProcessAMDGPU.cpp b/lldb/tools/lldb-server/Plugins/AMDGPU/ProcessAMDGPU.cpp index 67a081021910c..66a9ed061dced 100644 --- a/lldb/tools/lldb-server/Plugins/AMDGPU/ProcessAMDGPU.cpp +++ b/lldb/tools/lldb-server/Plugins/AMDGPU/ProcessAMDGPU.cpp @@ -146,6 +146,11 @@ void ProcessAMDGPU::SetLaunchInfo(ProcessLaunchInfo &launch_info) { static_cast(launch_info); } +void ProcessAMDGPU::HandleNativeProcessExit(const WaitStatus &exit_status) { + // Set our exit status to match the native process and notify delegates + SetExitStatus(exit_status, true); +} + bool ProcessAMDGPU::GetProcessInfo(ProcessInstanceInfo &proc_info) { Log *log = GetLog(GDBRLog::Plugin); LLDB_LOGF(log, "ProcessAMDGPU::%s() entered", __FUNCTION__); diff --git a/lldb/tools/lldb-server/Plugins/AMDGPU/ProcessAMDGPU.h b/lldb/tools/lldb-server/Plugins/AMDGPU/ProcessAMDGPU.h index 2db9096f6104f..f53a9cc8535fe 100644 --- a/lldb/tools/lldb-server/Plugins/AMDGPU/ProcessAMDGPU.h +++ b/lldb/tools/lldb-server/Plugins/AMDGPU/ProcessAMDGPU.h @@ -86,6 +86,9 @@ class ProcessAMDGPU : public NativeProcessProtocol { std::optional GetGPUDynamicLoaderLibraryInfos(const GPUDynamicLoaderArgs &args) override; + /// Called when the native process exits to exit the GPU process + void HandleNativeProcessExit(const WaitStatus &exit_status) override; + bool handleWaveStop(amd_dbgapi_event_id_t eventId); bool handleDebugEvent(amd_dbgapi_event_id_t eventId, diff --git a/lldb/tools/lldb-server/Plugins/MockGPU/LLDBServerPluginMockGPU.cpp b/lldb/tools/lldb-server/Plugins/MockGPU/LLDBServerPluginMockGPU.cpp index 5c69fdbeebb30..d1a0ccc4d2b96 100644 --- a/lldb/tools/lldb-server/Plugins/MockGPU/LLDBServerPluginMockGPU.cpp +++ b/lldb/tools/lldb-server/Plugins/MockGPU/LLDBServerPluginMockGPU.cpp @@ -168,9 +168,8 @@ void LLDBServerPluginMockGPU::NativeProcessDidExit( const WaitStatus &exit_status) { // Tell the GPU process to exit NativeProcessProtocol *gpu_process = m_gdb_server->GetCurrentProcess(); - if (auto *mock_gpu_process = static_cast(gpu_process)) { + if (auto *mock_gpu_process = static_cast(gpu_process)) mock_gpu_process->HandleNativeProcessExit(exit_status); - } } llvm::Expected diff --git a/lldb/tools/lldb-server/Plugins/MockGPU/ProcessMockGPU.h b/lldb/tools/lldb-server/Plugins/MockGPU/ProcessMockGPU.h index 9e5e38c931040..1910daab8dda1 100644 --- a/lldb/tools/lldb-server/Plugins/MockGPU/ProcessMockGPU.h +++ b/lldb/tools/lldb-server/Plugins/MockGPU/ProcessMockGPU.h @@ -107,7 +107,7 @@ class Manager : public NativeProcessProtocol::Manager { void SetLaunchInfo(ProcessLaunchInfo &launch_info); /// Called when the native process exits to set the GPU process exit status - void HandleNativeProcessExit(const WaitStatus &exit_status); + void HandleNativeProcessExit(const WaitStatus &exit_status) override; }; From c22a71d39bb6dd2a94458db5a5d476e39dcf81ac Mon Sep 17 00:00:00 2001 From: qxy11 Date: Thu, 18 Sep 2025 12:55:09 -0700 Subject: [PATCH 3/4] Remove HandleNativeProcessExit Summary: Have each plugin process decide how they want to handle native process exit. --- lldb/include/lldb/Host/common/NativeProcessProtocol.h | 3 --- lldb/tools/lldb-server/Plugins/AMDGPU/ProcessAMDGPU.h | 2 +- lldb/tools/lldb-server/Plugins/MockGPU/ProcessMockGPU.h | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/lldb/include/lldb/Host/common/NativeProcessProtocol.h b/lldb/include/lldb/Host/common/NativeProcessProtocol.h index f8422eed409f8..82a8458c7c069 100644 --- a/lldb/include/lldb/Host/common/NativeProcessProtocol.h +++ b/lldb/include/lldb/Host/common/NativeProcessProtocol.h @@ -301,9 +301,6 @@ class NativeProcessProtocol { return std::nullopt; }; - // Handle exiting the GPU process when a native process exits. - virtual void HandleNativeProcessExit(const WaitStatus &exit_status) {}; - /// Extension flag constants, returned by Manager::GetSupportedExtensions() /// and passed to SetEnabledExtension() enum class Extension { diff --git a/lldb/tools/lldb-server/Plugins/AMDGPU/ProcessAMDGPU.h b/lldb/tools/lldb-server/Plugins/AMDGPU/ProcessAMDGPU.h index f53a9cc8535fe..1dd4ee0c6c9f1 100644 --- a/lldb/tools/lldb-server/Plugins/AMDGPU/ProcessAMDGPU.h +++ b/lldb/tools/lldb-server/Plugins/AMDGPU/ProcessAMDGPU.h @@ -87,7 +87,7 @@ class ProcessAMDGPU : public NativeProcessProtocol { GetGPUDynamicLoaderLibraryInfos(const GPUDynamicLoaderArgs &args) override; /// Called when the native process exits to exit the GPU process - void HandleNativeProcessExit(const WaitStatus &exit_status) override; + void HandleNativeProcessExit(const WaitStatus &exit_status); bool handleWaveStop(amd_dbgapi_event_id_t eventId); diff --git a/lldb/tools/lldb-server/Plugins/MockGPU/ProcessMockGPU.h b/lldb/tools/lldb-server/Plugins/MockGPU/ProcessMockGPU.h index 1910daab8dda1..9e5e38c931040 100644 --- a/lldb/tools/lldb-server/Plugins/MockGPU/ProcessMockGPU.h +++ b/lldb/tools/lldb-server/Plugins/MockGPU/ProcessMockGPU.h @@ -107,7 +107,7 @@ class Manager : public NativeProcessProtocol::Manager { void SetLaunchInfo(ProcessLaunchInfo &launch_info); /// Called when the native process exits to set the GPU process exit status - void HandleNativeProcessExit(const WaitStatus &exit_status) override; + void HandleNativeProcessExit(const WaitStatus &exit_status); }; From 1dba57c9bae2964f459a659a963fe87101437d9e Mon Sep 17 00:00:00 2001 From: qxy11 Date: Thu, 18 Sep 2025 16:51:05 -0700 Subject: [PATCH 4/4] Remote auto and brackets --- .../Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 29b285dd28de0..5e8b4b3f46694 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -1143,9 +1143,8 @@ void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited( // Notify GPU plugins that the native process has exited std::optional exit_status = process->GetExitStatus(); if (exit_status.has_value()) - for (auto &plugin_up : m_plugins) { + for (std::unique_ptr &plugin_up : m_plugins) plugin_up->NativeProcessDidExit(*exit_status); - } PacketResult result = SendStopReasonForState( *process, StateType::eStateExited, /*force_synchronous=*/false);