Skip to content

Commit

Permalink
Fix leaking of memory and memory contexts in Foreign Constraint Graphs (
Browse files Browse the repository at this point in the history
#7236)

DESCRIPTION: Fix leaking of memory and memory contexts in Foreign
Constraint Graphs

Previously, every time we (re)created the Foreign Constraint
Relationship Graph, we created a new Memory Context while loosing a
reference to the previous context. This old context could still have
left over memory in there causing a memory leak.

With this patch we statically have one memory context that we lazily
initialize the first time we create our foreign constraint relationship
graph. On every subsequent creation, beside destroying our previous
hashmap we also reset our memory context to remove any left over
references.
  • Loading branch information
thanodnl committed Oct 9, 2023
1 parent 3b908ee commit e59ffbf
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 28 deletions.
57 changes: 30 additions & 27 deletions src/backend/distributed/utils/foreign_key_relationship.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "distributed/version_compat.h"
#include "nodes/pg_list.h"
#include "storage/lockdefs.h"
#include "utils/catcache.h"
#include "utils/fmgroids.h"
#include "utils/hsearch.h"
#include "common/hashfn.h"
Expand Down Expand Up @@ -96,6 +97,8 @@ static List * GetConnectedListHelper(ForeignConstraintRelationshipNode *node,
bool isReferencing);
static List * GetForeignConstraintRelationshipHelper(Oid relationId, bool isReferencing);

MemoryContext ForeignConstraintRelationshipMemoryContext = NULL;


/*
* GetForeignKeyConnectedRelationIdList returns a list of relation id's for
Expand Down Expand Up @@ -321,17 +324,36 @@ CreateForeignConstraintRelationshipGraph()
return;
}

ClearForeignConstraintRelationshipGraphContext();
/*
* Lazily create our memory context once and reset on every reuse.
* Since we have cleared and invalidated the fConstraintRelationshipGraph, right
* before we can simply reset the context if it was already existing.
*/
if (ForeignConstraintRelationshipMemoryContext == NULL)
{
/* make sure we've initialized CacheMemoryContext */
if (CacheMemoryContext == NULL)
{
CreateCacheMemoryContext();
}

ForeignConstraintRelationshipMemoryContext = AllocSetContextCreate(
CacheMemoryContext,
"Foreign Constraint Relationship Graph Context",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
}
else
{
fConstraintRelationshipGraph = NULL;
MemoryContextReset(ForeignConstraintRelationshipMemoryContext);
}

MemoryContext fConstraintRelationshipMemoryContext = AllocSetContextCreateInternal(
CacheMemoryContext,
"Forign Constraint Relationship Graph Context",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
Assert(fConstraintRelationshipGraph == NULL);

MemoryContext oldContext = MemoryContextSwitchTo(
fConstraintRelationshipMemoryContext);
ForeignConstraintRelationshipMemoryContext);

fConstraintRelationshipGraph = (ForeignConstraintRelationshipGraph *) palloc(
sizeof(ForeignConstraintRelationshipGraph));
Expand Down Expand Up @@ -631,22 +653,3 @@ CreateOrFindNode(HTAB *adjacencyLists, Oid relid)

return node;
}


/*
* ClearForeignConstraintRelationshipGraphContext clear all the allocated memory obtained
* for foreign constraint relationship graph. Since all the variables of relationship
* graph was obtained within the same context, destroying hash map is enough as
* it deletes the context.
*/
void
ClearForeignConstraintRelationshipGraphContext()
{
if (fConstraintRelationshipGraph == NULL)
{
return;
}

hash_destroy(fConstraintRelationshipGraph->nodeMap);
fConstraintRelationshipGraph = NULL;
}
1 change: 0 additions & 1 deletion src/include/distributed/foreign_key_relationship.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ extern bool ShouldUndistributeCitusLocalTable(Oid relationId);
extern List * ReferencedRelationIdList(Oid relationId);
extern List * ReferencingRelationIdList(Oid relationId);
extern void SetForeignConstraintRelationshipGraphInvalid(void);
extern void ClearForeignConstraintRelationshipGraphContext(void);
extern bool OidVisited(HTAB *oidVisitedMap, Oid oid);
extern void VisitOid(HTAB *oidVisitedMap, Oid oid);

Expand Down

0 comments on commit e59ffbf

Please sign in to comment.