diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -521,6 +521,8 @@ bool GetSaveCoreSupported() const; + llvm::Expected KillProcess(lldb::pid_t pid); + protected: LazyBool m_supports_not_sending_acks = eLazyBoolCalculate; LazyBool m_supports_thread_suffix = eLazyBoolCalculate; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -4265,3 +4265,21 @@ // check whether it is an old version of lldb-server. return GetThreadSuffixSupported(); } + +llvm::Expected GDBRemoteCommunicationClient::KillProcess(lldb::pid_t pid) { + StringExtractorGDBRemote response; + GDBRemoteCommunication::ScopedTimeout(*this, seconds(3)); + + if (SendPacketAndWaitForResponse("k", response, GetPacketTimeout()) != + PacketResult::Success) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "failed to send k packet"); + + char packet_cmd = response.GetChar(0); + if (packet_cmd == 'W' || packet_cmd == 'X') + return response.GetHexU8(); + + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "unexpected response to k packet: %s", + response.GetStringRef().str().c_str()); +} 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 @@ -2394,7 +2394,6 @@ } Status ProcessGDBRemote::DoDestroy() { - Status error; Log *log = GetLog(GDBRLog::Process); LLDB_LOGF(log, "ProcessGDBRemote::DoDestroy()"); @@ -2404,54 +2403,35 @@ if (m_gdb_comm.IsConnected()) { if (m_public_state.GetValue() != eStateAttaching) { - StringExtractorGDBRemote response; - GDBRemoteCommunication::ScopedTimeout(m_gdb_comm, - std::chrono::seconds(3)); - - if (m_gdb_comm.SendPacketAndWaitForResponse("k", response, - GetInterruptTimeout()) == - GDBRemoteCommunication::PacketResult::Success) { - char packet_cmd = response.GetChar(0); + llvm::Expected kill_res = m_gdb_comm.KillProcess(GetID()); - if (packet_cmd == 'W' || packet_cmd == 'X') { + if (kill_res) { + exit_status = kill_res.get(); #if defined(__APPLE__) - // For Native processes on Mac OS X, we launch through the Host - // Platform, then hand the process off to debugserver, which becomes - // the parent process through "PT_ATTACH". Then when we go to kill - // the process on Mac OS X we call ptrace(PT_KILL) to kill it, then - // we call waitpid which returns with no error and the correct - // status. But amusingly enough that doesn't seem to actually reap - // the process, but instead it is left around as a Zombie. Probably - // the kernel is in the process of switching ownership back to lldb - // which was the original parent, and gets confused in the handoff. - // Anyway, so call waitpid here to finally reap it. - PlatformSP platform_sp(GetTarget().GetPlatform()); - if (platform_sp && platform_sp->IsHost()) { - int status; - ::pid_t reap_pid; - reap_pid = waitpid(GetID(), &status, WNOHANG); - LLDB_LOGF(log, "Reaped pid: %d, status: %d.\n", reap_pid, status); - } -#endif - SetLastStopPacket(response); - ClearThreadIDList(); - exit_status = response.GetHexU8(); - } else { - LLDB_LOGF(log, - "ProcessGDBRemote::DoDestroy - got unexpected response " - "to k packet: %s", - response.GetStringRef().data()); - exit_string.assign("got unexpected response to k packet: "); - exit_string.append(std::string(response.GetStringRef())); + // For Native processes on Mac OS X, we launch through the Host + // Platform, then hand the process off to debugserver, which becomes + // the parent process through "PT_ATTACH". Then when we go to kill + // the process on Mac OS X we call ptrace(PT_KILL) to kill it, then + // we call waitpid which returns with no error and the correct + // status. But amusingly enough that doesn't seem to actually reap + // the process, but instead it is left around as a Zombie. Probably + // the kernel is in the process of switching ownership back to lldb + // which was the original parent, and gets confused in the handoff. + // Anyway, so call waitpid here to finally reap it. + PlatformSP platform_sp(GetTarget().GetPlatform()); + if (platform_sp && platform_sp->IsHost()) { + int status; + ::pid_t reap_pid; + reap_pid = waitpid(GetID(), &status, WNOHANG); + LLDB_LOGF(log, "Reaped pid: %d, status: %d.\n", reap_pid, status); } +#endif + ClearThreadIDList(); + exit_string.assign("killed"); } else { - LLDB_LOGF(log, "ProcessGDBRemote::DoDestroy - failed to send k packet"); - exit_string.assign("failed to send the k packet"); + exit_string.assign(llvm::toString(kill_res.takeError())); } } else { - LLDB_LOGF(log, - "ProcessGDBRemote::DoDestroy - killed or interrupted while " - "attaching"); exit_string.assign("killed or interrupted while attaching."); } } else { @@ -2465,7 +2445,7 @@ StopAsyncThread(); KillDebugserverProcess(); - return error; + return Status(); } void ProcessGDBRemote::SetLastStopPacket(