diff --git a/src/Application.cpp b/src/Application.cpp index 7af4761d..1f7c39fb 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -7,6 +7,7 @@ #include "src/Logger/Logger.hpp" #include "src/Helpers/Paths.hpp" +#include "src/Helpers/Process.hpp" #include "src/Exceptions/InvalidConfig.hpp" @@ -509,7 +510,7 @@ namespace Bloom } void Application::onDebugSessionFinished(const Events::DebugSessionFinished& event) { - if (this->environmentConfig->shutdownPostDebugSession) { + if (this->environmentConfig->shutdownPostDebugSession || Process::isManagedByClion()) { this->shutdown(); } } diff --git a/src/DebugServer/Gdb/CommandPackets/Detach.cpp b/src/DebugServer/Gdb/CommandPackets/Detach.cpp index 42feefdd..c8a4ed47 100644 --- a/src/DebugServer/Gdb/CommandPackets/Detach.cpp +++ b/src/DebugServer/Gdb/CommandPackets/Detach.cpp @@ -24,7 +24,7 @@ namespace Bloom::DebugServer::Gdb::CommandPackets Logger::debug("Handling Detach packet"); try { - if (Process::isManagedByClion(Process::getParentProcessId())) { + if (Process::isManagedByClion()) { targetControllerConsole.suspendTargetController(); } diff --git a/src/DebugServer/Gdb/GdbRspDebugServer.cpp b/src/DebugServer/Gdb/GdbRspDebugServer.cpp index c50e4985..caa62934 100644 --- a/src/DebugServer/Gdb/GdbRspDebugServer.cpp +++ b/src/DebugServer/Gdb/GdbRspDebugServer.cpp @@ -125,7 +125,7 @@ namespace Bloom::DebugServer::Gdb std::bind(&GdbRspDebugServer::onTargetExecutionStopped, this, std::placeholders::_1) ); - if (Process::isManagedByClion(Process::getParentProcessId())) { + if (Process::isManagedByClion()) { Logger::warning( "Bloom's process is being managed by CLion - Bloom will automatically shutdown upon detaching from GDB." ); diff --git a/src/Helpers/Process.cpp b/src/Helpers/Process.cpp index 6938e7da..0499760c 100644 --- a/src/Helpers/Process.cpp +++ b/src/Helpers/Process.cpp @@ -2,6 +2,7 @@ #include #include +#include namespace Bloom { @@ -13,47 +14,50 @@ namespace Bloom return getppid(); } - bool Process::isManagedByClion(::pid_t processId) { - static auto cachedResult = std::optional(); + bool Process::isManagedByClion(std::optional<::pid_t> parentProcessId) { + if (!parentProcessId.has_value()) { + parentProcessId = Process::getParentProcessId(); + } - if (cachedResult.has_value()) { - return cachedResult.value(); + static auto cachedResultsByProcessId = std::map<::pid_t, bool>(); + + if (cachedResultsByProcessId.contains(*parentProcessId)) { + return cachedResultsByProcessId.at(*parentProcessId); } // Walk the process tree until we find CLion + auto processId = *parentProcessId; while (processId != 0) { const auto processInfo = Process::getProcessInfo(processId); - if (!processInfo.has_value()) { + if (!processInfo) { break; } - auto* processInfoPtr = processInfo.value(); - - const auto commandLine = std::string(processInfoPtr->cmd); + const auto commandLine = std::string(processInfo->cmd); if (commandLine.find("clion.sh") != std::string::npos) { - freeproc(processInfoPtr); - cachedResult = true; + cachedResultsByProcessId[*parentProcessId] = true; return true; } - processId = processInfoPtr->ppid; - freeproc(processInfoPtr); + processId = processInfo->ppid; } - cachedResult = true; + cachedResultsByProcessId[*parentProcessId] = false; return false; } - std::optional<::proc_t*> Process::getProcessInfo(::pid_t processId) { - auto* proc = ::openproc(PROC_FILLSTAT | PROC_FILLARG | PROC_PID, &processId); - auto* processInfo = ::readproc(proc, NULL); + Process::ProcT Process::getProcessInfo(::pid_t processId) { + auto proc = std::unique_ptr<::PROCTAB, decltype(&::closeproc)>( + ::openproc(PROC_FILLSTAT | PROC_FILLARG | PROC_PID, &processId), + ::closeproc + ); + auto processInfo = ProcT(::readproc(proc.get(), NULL), ::freeproc); if (processInfo == NULL) { - return std::nullopt; + return ProcT(nullptr, ::freeproc); } - closeproc(proc); return processInfo; } } diff --git a/src/Helpers/Process.hpp b/src/Helpers/Process.hpp index f49e7157..7e0be180 100644 --- a/src/Helpers/Process.hpp +++ b/src/Helpers/Process.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include namespace Bloom @@ -25,12 +26,16 @@ namespace Bloom /** * Returns true if the given process is managed by CLion. * - * @param processId + * @param parentProcessId + * If not provided, this function will perform the check against the current process. + * * @return */ - static bool isManagedByClion(::pid_t processId); + static bool isManagedByClion(std::optional<::pid_t> parentProcessId = std::nullopt); + private: - static std::optional<::proc_t*> getProcessInfo(::pid_t processId); + using ProcT = std::unique_ptr<::proc_t, decltype(&::freeproc)>; + static ProcT getProcessInfo(::pid_t processId); }; }