1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-30 19:23:07 +03:00

MCOL-4043 Fix memory leaks - 1

simpleScalarFilterToParseTree() performs a dynamic allocation
of a ParseTree object, but this memory is never freed later.
We now keep track of this allocation and perform the delete
in the JobList dtor after the query finishes.
This commit is contained in:
Gagan Goel
2020-06-11 19:01:40 -04:00
parent feee26f1ab
commit 881091c535
7 changed files with 54 additions and 2 deletions

View File

@ -150,8 +150,14 @@ SimpleFilter::SimpleFilter(const SimpleFilter& rhs) :
SimpleFilter::~SimpleFilter()
{
//delete fOp;
if (fLhs != NULL)
delete fLhs;
if (fRhs != NULL)
delete fRhs;
fLhs = NULL;
fRhs = NULL;
}
/**

View File

@ -364,6 +364,11 @@ struct JobInfo
bool isDML;
std::string timeZone;
// This is for tracking any dynamically allocated ParseTree objects
// in simpleScalarFilterToParseTree() for later deletion in
// JobList::~JobList()
std::vector<std::pair<execplan::ParseTree*, execplan::ParseTree*>> dynamicParseTreeVec;
private:
//defaults okay
//JobInfo(const JobInfo& rhs);

View File

@ -3269,6 +3269,12 @@ void doOR(ParseTree* n, JobInfo& jobInfo, bool tryCombine)
ccp->left(parseTree->left());
ccp->right(parseTree->right());
ccp->data(parseTree->data());
jobInfo.dynamicParseTreeVec.push_back(make_pair(parseTree, ccp));
}
else if (parseTree)
{
delete parseTree;
parseTree = NULL;
}
}

View File

@ -192,7 +192,10 @@ void ssfInHaving(ParseTree* pt, void* obj)
pt->right(parseTree->right());
pt->data(parseTree->data());
jobInfo->dynamicParseTreeVec.push_back(make_pair(parseTree, pt));
// don't delete the parseTree, it has been placed in the plan.
// Instead, we use the dynamicParseTreeVec above for deletion
// in the JobList dtor after the query executes.
// delete parseTree;
}
else
@ -627,7 +630,10 @@ void doSimpleScalarFilter(ParseTree* p, JobInfo& jobInfo)
// create job steps for each simple filter
JLF_ExecPlanToJobList::walkTree(parseTree, jobInfo);
jobInfo.dynamicParseTreeVec.push_back(make_pair(parseTree, ccp));
// don't delete the parseTree, it has been placed in the plan.
// Instead, we use the dynamicParseTreeVec above for deletion
// in the JobList dtor after the query executes.
// delete parseTree;
}
else

View File

@ -142,6 +142,26 @@ JobList::~JobList()
(*iter)->join();
}
}
for (auto& parseTree : fDynamicParseTreeVec)
{
if (parseTree.first)
{
delete parseTree.first;
parseTree.first = NULL;
// Note that we don't delete parseTree.second here,
// that is handled by CalpontSelectExecutionPlan::unserialize().
// parseTree.first already deleted the objects pointed to by
// parseTree.second->left()/right()/data(), so we set the
// pointers to NULL here.
if (parseTree.second)
{
parseTree.second->left((ParseTree*) (NULL));
parseTree.second->right((ParseTree*) (NULL));
parseTree.second->data((TreeNode*) (NULL));
}
}
}
}
catch (exception& ex)
{

View File

@ -34,6 +34,7 @@
#include "jobstep.h"
#include "bytestream.h"
#include "parsetree.h"
#ifndef __GNUC__
# ifndef __attribute__
@ -190,6 +191,12 @@ public:
fPmsConfigured = pms;
}
virtual void setDynamicParseTreeVec(
const std::vector<std::pair<execplan::ParseTree*, execplan::ParseTree*>>& dynamicParseTreeVec)
{
fDynamicParseTreeVec = dynamicParseTreeVec;
}
protected:
//defaults okay
//JobList(const JobList& rhs);
@ -217,6 +224,7 @@ protected:
volatile uint32_t fAborted;
uint32_t fPriority; //higher #s = higher priority
std::vector<std::pair<execplan::ParseTree*, execplan::ParseTree*>> fDynamicParseTreeVec;
};
class TupleJobList : public JobList

View File

@ -2003,6 +2003,7 @@ SJLP makeJobList_(
jl->addQuery(querySteps);
jl->addProject(projectSteps);
jl->addDelivery(deliverySteps);
jl->setDynamicParseTreeVec(jobInfo.dynamicParseTreeVec);
dynamic_cast<TupleJobList*>(jl)->setDeliveryFlag(true);
}