mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-05-28 17:16:29 +03:00
Fix a memory leak in the debugger session where memory was never released after session due to cyclic references in ModelVariableNode.
Fix an incorrect std::move in `DebuggerClientDap::variables` which could have caused incorrect states. Fix invalid memory access in `LSPDocumentClient::requestSemanticHighlighting`.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -848,24 +848,35 @@ bool DebuggerClientDap::variables( int variablesReference, Variable::Type filter
|
||||
[this, responseCb = std::move( responseCb )]( const Response& response,
|
||||
const nlohmann::json& request ) {
|
||||
const int variablesReference = request.value( DAP_VARIABLES_REFERENCE, 0 );
|
||||
|
||||
if ( response.success ) {
|
||||
auto variableList( Variable::parseList( response.body[DAP_VARIABLES] ) );
|
||||
auto variableList = Variable::parseList( response.body[DAP_VARIABLES] );
|
||||
if ( responseCb ) {
|
||||
responseCb( variablesReference, std::move( variableList ) );
|
||||
} else {
|
||||
for ( auto listener : mListeners )
|
||||
listener->variables( variablesReference, std::move( variableList ),
|
||||
mCurrentSessionId );
|
||||
} else if ( !mListeners.empty() ) {
|
||||
if ( mListeners.size() == 1 ) {
|
||||
// Move directly to single listener
|
||||
mListeners[0]->variables( variablesReference, std::move( variableList ),
|
||||
mCurrentSessionId );
|
||||
} else {
|
||||
// Copy for multiple listeners
|
||||
for ( auto listener : mListeners ) {
|
||||
std::vector<Variable> variableListCopy = variableList;
|
||||
listener->variables( variablesReference, std::move( variableListCopy ),
|
||||
mCurrentSessionId );
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::vector<Variable> variableList;
|
||||
std::vector<Variable> variableList; // Single empty vector
|
||||
if ( responseCb ) {
|
||||
responseCb( variablesReference, std::move( variableList ) );
|
||||
} else {
|
||||
for ( auto listener : mListeners )
|
||||
listener->variables( variablesReference, std::move( variableList ),
|
||||
} else if ( !mListeners.empty() ) {
|
||||
// Share empty vector with all listeners
|
||||
for ( auto listener : mListeners ) {
|
||||
std::vector<Variable> variableListCopy = variableList;
|
||||
listener->variables( variablesReference, std::move( variableListCopy ),
|
||||
mCurrentSessionId );
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -34,7 +34,7 @@ DebuggerClientListener::DebuggerClientListener( DebuggerClient* client, Debugger
|
||||
}
|
||||
|
||||
DebuggerClientListener::~DebuggerClientListener() {
|
||||
resetState();
|
||||
resetState( true );
|
||||
auto sdc = getStatusDebuggerController();
|
||||
if ( !mPlugin->isShuttingDown() && sdc ) {
|
||||
if ( sdc->getUIThreads() )
|
||||
@@ -243,7 +243,7 @@ void DebuggerClientListener::configured( const SessionId& ) {}
|
||||
|
||||
void DebuggerClientListener::failed( const SessionId& ) {
|
||||
mPlugin->exitDebugger();
|
||||
resetState();
|
||||
resetState( true );
|
||||
}
|
||||
|
||||
void DebuggerClientListener::debuggeeRunning( const SessionId& ) {}
|
||||
@@ -251,13 +251,13 @@ void DebuggerClientListener::debuggeeRunning( const SessionId& ) {}
|
||||
void DebuggerClientListener::debuggeeTerminated( const SessionId& ) {
|
||||
if ( mClient->sessionsActive() == 0 ) {
|
||||
mPlugin->exitDebugger();
|
||||
resetState();
|
||||
resetState( true );
|
||||
}
|
||||
}
|
||||
|
||||
void DebuggerClientListener::capabilitiesReceived( const Capabilities& /*capabilities*/ ) {}
|
||||
|
||||
void DebuggerClientListener::resetState() {
|
||||
void DebuggerClientListener::resetState( bool full ) {
|
||||
mStoppedData = {};
|
||||
mCurrentScopePos = {};
|
||||
mCurrentFrameId = 0;
|
||||
@@ -265,12 +265,13 @@ void DebuggerClientListener::resetState() {
|
||||
mThreadsModel->resetThreads();
|
||||
if ( mStackModel )
|
||||
mStackModel->resetStack();
|
||||
mVariablesHolder->clear();
|
||||
mVariablesHolder->clear( full );
|
||||
mScopeRef.clear();
|
||||
}
|
||||
|
||||
void DebuggerClientListener::debuggeeExited( int /*exitCode*/, const SessionId& ) {
|
||||
mPlugin->exitDebugger();
|
||||
resetState();
|
||||
resetState( true );
|
||||
}
|
||||
|
||||
void DebuggerClientListener::debuggeeStopped( const StoppedEvent& event, const SessionId& ) {
|
||||
@@ -320,7 +321,7 @@ void DebuggerClientListener::debuggeeStopped( const StoppedEvent& event, const S
|
||||
}
|
||||
|
||||
void DebuggerClientListener::debuggeeContinued( const ContinuedEvent&, const SessionId& ) {
|
||||
resetState();
|
||||
resetState( false );
|
||||
|
||||
UISceneNode* sceneNode = mPlugin->getUISceneNode();
|
||||
sceneNode->runOnMainThread( [sceneNode] { sceneNode->getRoot()->invalidateDraw(); } );
|
||||
|
||||
@@ -133,7 +133,7 @@ class DebuggerClientListener : public DebuggerClient::Listener {
|
||||
|
||||
StatusDebuggerController* getStatusDebuggerController() const;
|
||||
|
||||
void resetState();
|
||||
void resetState( bool full );
|
||||
|
||||
void changeScope( const StackFrame& f );
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ void ModelVariableNode::addChild( NodePtr child ) {
|
||||
}
|
||||
|
||||
ModelVariableNode::NodePtr ModelVariableNode::getParent() const {
|
||||
return parent;
|
||||
return parent.lock();
|
||||
}
|
||||
|
||||
std::optional<ModelVariableNode::NodePtr> ModelVariableNode::getChild( int variablesReference ) {
|
||||
@@ -166,6 +166,10 @@ VariablesHolder::VariablesHolder( UISceneNode* sceneNode ) :
|
||||
mNodeMap[0] = mRootNode;
|
||||
}
|
||||
|
||||
VariablesHolder::~VariablesHolder() {
|
||||
clear( true );
|
||||
}
|
||||
|
||||
void VariablesHolder::addVariables( const int variablesReference, std::vector<Variable>&& vars ) {
|
||||
Lock l( mMutex );
|
||||
auto parentNode = getNodeByReference( variablesReference );
|
||||
@@ -244,6 +248,7 @@ void VariablesHolder::clear( bool all ) {
|
||||
if ( all ) {
|
||||
mNodeMap.clear();
|
||||
mCurrentLocation = {};
|
||||
mExpandedStates.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +261,8 @@ VariablePath VariablesHolder::buildVariablePath( ModelVariableNode* node ) const
|
||||
VariablePath path;
|
||||
while ( node && node != mRootNode.get() ) {
|
||||
path.push_back( node->getName() );
|
||||
node = node->parent ? node->parent.get() : nullptr;
|
||||
auto parentNode = node->parent.lock();
|
||||
node = parentNode.get();
|
||||
}
|
||||
std::reverse( path.begin(), path.end() );
|
||||
return path;
|
||||
|
||||
@@ -68,6 +68,7 @@ namespace ecode {
|
||||
|
||||
struct ModelVariableNode : public std::enable_shared_from_this<ModelVariableNode> {
|
||||
using NodePtr = std::shared_ptr<ModelVariableNode>;
|
||||
using WeakNodePtr = std::weak_ptr<ModelVariableNode>;
|
||||
|
||||
ModelVariableNode( Variable&& var, NodePtr parent );
|
||||
|
||||
@@ -93,7 +94,7 @@ struct ModelVariableNode : public std::enable_shared_from_this<ModelVariableNode
|
||||
|
||||
NodePtr getParent() const;
|
||||
|
||||
NodePtr parent{ nullptr };
|
||||
WeakNodePtr parent;
|
||||
Variable var;
|
||||
std::vector<NodePtr> children;
|
||||
};
|
||||
@@ -127,6 +128,8 @@ class VariablesHolder {
|
||||
public:
|
||||
VariablesHolder( UISceneNode* sceneNode );
|
||||
|
||||
~VariablesHolder();
|
||||
|
||||
void addVariables( const int variablesReference, std::vector<Variable>&& vars );
|
||||
|
||||
void addChild( ModelVariableNode::NodePtr child );
|
||||
|
||||
@@ -175,9 +175,9 @@ void LSPDocumentClient::requestSemanticHighlighting( bool reqFull ) {
|
||||
Uint64 docModId = mDoc->getModificationId();
|
||||
mServer->documentSemanticTokensFull(
|
||||
mDoc->getURI(), delta, reqId, range,
|
||||
[docClient, uri, server, docModId, this]( const auto&, LSPSemanticTokensDelta&& deltas ) {
|
||||
BoolScopedOp op( mProcessingSemanticTokensResponse, true );
|
||||
[docClient, uri, server, docModId]( const auto&, LSPSemanticTokensDelta&& deltas ) {
|
||||
if ( server->hasDocumentClient( docClient ) && server->hasDocument( uri ) ) {
|
||||
BoolScopedOp op( docClient->mProcessingSemanticTokensResponse, true );
|
||||
docClient->mWaitingSemanticTokensResponse = false;
|
||||
docClient->processTokens( std::move( deltas ), docModId );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user