From 7bfbc9de2f0142584089c6778a09ccb7fe1bc4e9 Mon Sep 17 00:00:00 2001 From: Jingtang Zhang Date: Tue, 19 Aug 2025 11:13:54 +0800 Subject: [PATCH] Fix SMgrRelation object memory leak in DropRelationFiles SMgrRelation object would stay alive until end of a transaction, or by explicit smgrdestroy* call outside of a transaction by background processes or WAL redo, after the underlying storage is gone. Currently, the object is closed but not destroyed during WAL redo, causing memory leak by those already destroyed relations. Fixed by explicit destroy the objects at the end of DropRelationFiles. --- src/backend/storage/smgr/md.c | 2 +- src/backend/storage/smgr/smgr.c | 10 ++++++++-- src/include/storage/smgr.h | 1 + 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c index 2ccb0faceb5..f9d65cb5b65 100644 --- a/src/backend/storage/smgr/md.c +++ b/src/backend/storage/smgr/md.c @@ -1607,7 +1607,7 @@ DropRelationFiles(RelFileLocator *delrels, int ndelrels, bool isRedo) smgrdounlinkall(srels, ndelrels, isRedo); for (i = 0; i < ndelrels; i++) - smgrclose(srels[i]); + smgrdestroy(srels[i]); pfree(srels); } diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c index bce37a36d51..f30b8957bd5 100644 --- a/src/backend/storage/smgr/smgr.c +++ b/src/backend/storage/smgr/smgr.c @@ -163,7 +163,6 @@ static dlist_head unpinned_relns; /* local function prototypes */ static void smgrshutdown(int code, Datum arg); -static void smgrdestroy(SMgrRelation reln); static void smgr_aio_reopen(PgAioHandle *ioh); static char *smgr_aio_describe_identity(const PgAioTargetData *sd); @@ -318,8 +317,15 @@ smgrunpin(SMgrRelation reln) /* * smgrdestroy() -- Delete an SMgrRelation object. + * + * Remove the object out of hashtable. We must ensure there is no dangling + * reference to the object by this time. + * + * Called at the end of a transaction through AtEOXact_SMgr(). Also called + * outside of a transaction through smgrdestroyall() or directly itself, + * for background processes and WAL redo. */ -static void +void smgrdestroy(SMgrRelation reln) { ForkNumber forknum; diff --git a/src/include/storage/smgr.h b/src/include/storage/smgr.h index 3964d9334b3..3b07b3ceea1 100644 --- a/src/include/storage/smgr.h +++ b/src/include/storage/smgr.h @@ -82,6 +82,7 @@ extern bool smgrexists(SMgrRelation reln, ForkNumber forknum); extern void smgrpin(SMgrRelation reln); extern void smgrunpin(SMgrRelation reln); extern void smgrclose(SMgrRelation reln); +extern void smgrdestroy(SMgrRelation reln); extern void smgrdestroyall(void); extern void smgrrelease(SMgrRelation reln); extern void smgrreleaseall(void); -- 2.39.3