Commit 6a4f671d authored by Igor Kushnir's avatar Igor Kushnir

Destroy not started debug sessions

When a debug session is stopped via MIDebugSession::stopDebugger() and
discarded while the s_dbgNotStarted state is still on, the session is
never destroyed. This is a genuine resource leak because the number of
such unused but not destroyed debug sessions is unlimited.

The leak can be easily reproduced by triggering Debug Launch with a
nonexistent executable specified in the current launch configuration.
A more difficult way to reproduce the leak is to Debug-Launch many times
in quick succession: some sessions will never reach
MIDebugSession::startDebugging() and debug-print the following line:
kdevelop.plugins.debuggercommon: Stopping debugger when it's not started

The leak is already detected in MIDebugSession::stopDebugger() when the
aforementioned message is debug-printed. Let us set the session state to
EndedState there. This session state change is connected to
DebugController::debuggerStateChanged(), which calls deleteLater() on
the debug session.
parent 37ff587e
......@@ -63,10 +63,14 @@ using namespace KDevelop;
using namespace KDevMI;
using namespace KDevMI::MI;
namespace {
constexpr DBGStateFlags notStartedDebuggerFlags{s_dbgNotStarted | s_appNotStarted};
}
MIDebugSession::MIDebugSession(MIDebuggerPlugin *plugin)
: m_procLineMaker(new ProcessLineMaker(this))
, m_commandQueue(new CommandQueue)
, m_debuggerState(s_dbgNotStarted | s_appNotStarted)
, m_debuggerState{notStartedDebuggerFlags}
, m_tty(nullptr)
, m_plugin(plugin)
{
......@@ -528,8 +532,14 @@ void MIDebugSession::restartDebugger()
void MIDebugSession::stopDebugger()
{
if (debuggerStateIsOn(s_dbgNotStarted)) {
// we are force to stop even before debugger started, just reset
qCDebug(DEBUGGERCOMMON) << "Stopping debugger when it's not started";
if (debuggerState() != notStartedDebuggerFlags) {
setDebuggerState(notStartedDebuggerFlags);
}
// Transition into EndedState to let DebugController destroy this session.
if (state() != EndedState) {
setSessionState(EndedState);
}
return;
}
......@@ -583,7 +593,7 @@ void MIDebugSession::killDebuggerImpl()
{
Q_ASSERT(m_debugger);
m_debugger->kill();
setDebuggerState(s_dbgNotStarted | s_appNotStarted);
setDebuggerState(notStartedDebuggerFlags);
raiseEvent(debugger_exited);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment