diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index f8989f7..ccc1c45 100644
--- a/src/backend/tcop/pquery.c
+++ b/src/backend/tcop/pquery.c
@@ -759,6 +759,11 @@ PortalRun(Portal portal, long count, bool isTopLevel,
 	saveResourceOwner = CurrentResourceOwner;
 	savePortalContext = PortalContext;
 	saveMemoryContext = CurrentMemoryContext;
+	/*
+	 *	Allocate a new ResourceOwner for the portal if not set.
+	 *	It can occur for held portals(committed holdable cursors).
+	 */
+	PortalAllocResourceOwner(portal);
 	PG_TRY();
 	{
 		ActivePortal = portal;
diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c
index 54bf16e..5013300 100644
--- a/src/backend/utils/mmgr/portalmem.c
+++ b/src/backend/utils/mmgr/portalmem.c
@@ -183,6 +183,37 @@ PortalListGetPrimaryStmt(List *stmts)
 	return NULL;
 }
 
+static void DelinkResownerFromPortal(ResourceOwner owner, void *arg)
+{
+	Portal	portal = (Portal) arg;
+
+	if (!portal)	return;
+	if (portal->resowner == NULL)
+		elog(DEBUG1, "resowner is already delinked from Portal(%p)", portal);
+	else if (owner != portal->resowner)
+		elog(DEBUG1, "the target ResourceOwner is different from the portal's resowner", portal);
+	else
+	{
+		elog(DEBUG1, "delinking resowner(%p) from Portal(%p)", portal->resowner, portal);
+		portal->resowner = NULL;
+	}
+	UnregisterResownerOnDeleteProc(owner, DelinkResownerFromPortal, arg);
+}
+
+/*
+ *	Allocate a new ResourceOwner for the portal if not set.
+ *	Also register an on delete procedure for the ResourceOwner.	
+ */
+void PortalAllocResourceOwner(Portal portal)
+{
+	if (portal->resowner)
+		return;
+	/* create a ResourceOwner for the portal */
+	portal->resowner = ResourceOwnerCreate(CurTransactionResourceOwner, "Portal");
+	/* register an on delete procedure for the ResourceOwner. */
+	RegisterResownerOnDeleteProc(portal->resowner, DelinkResownerFromPortal, portal);
+}
+
 /*
  * CreatePortal
  *		Returns a new portal given a name.
@@ -224,9 +255,7 @@ CreatePortal(const char *name, bool allowDup, bool dupSilent)
 										 ALLOCSET_SMALL_INITSIZE,
 										 ALLOCSET_SMALL_MAXSIZE);
 
-	/* create a resource owner for the portal */
-	portal->resowner = ResourceOwnerCreate(CurTransactionResourceOwner,
-										   "Portal");
+	PortalAllocResourceOwner(portal);
 
 	/* initialize portal fields that don't start off zero */
 	portal->status = PORTAL_NEW;
@@ -506,6 +535,8 @@ PortalDrop(Portal portal, bool isTopCommit)
 	/* drop cached plan reference, if any */
 	PortalReleaseCachedPlan(portal);
 
+	/* unregister the on delete procedure because resowner is set to NULL later in this routine */
+	UnregisterResownerOnDeleteProc(portal->resowner, NULL, portal);
 	/*
 	 * Release any resources still attached to the portal.	There are several
 	 * cases being covered here:
diff --git a/src/backend/utils/resowner/resowner.c b/src/backend/utils/resowner/resowner.c
index e7ec393..63930dd 100644
--- a/src/backend/utils/resowner/resowner.c
+++ b/src/backend/utils/resowner/resowner.c
@@ -98,6 +98,8 @@ typedef struct ResourceOwnerData
 	int			nfiles;			/* number of owned temporary files */
 	File	   *files;			/* dynamically allocated array */
 	int			maxfiles;		/* currently allocated array size */
+	ResourceOwnerDeleteProc	on_delete;
+	void			*on_delete_arg;
 }	ResourceOwnerData;
 
 
@@ -439,6 +441,10 @@ ResourceOwnerDelete(ResourceOwner owner)
 	if (owner->files)
 		pfree(owner->files);
 
+	/* call on delete procedure if exists */
+	if (owner->on_delete != NULL)
+		(*(owner->on_delete)) (owner, owner->on_delete_arg);
+
 	pfree(owner);
 }
 
@@ -537,6 +543,33 @@ UnregisterResourceReleaseCallback(ResourceReleaseCallback callback, void *arg)
 	}
 }
 
+/*
+ * Register or deregister an on delete procedure
+ *
+ */
+void
+RegisterResownerOnDeleteProc(ResourceOwner owner, ResourceOwnerDeleteProc proc, void *arg)
+{
+	if (!owner)
+		return;
+	owner->on_delete = proc;
+	owner->on_delete_arg = arg;
+}
+
+void
+UnregisterResownerOnDeleteProc(ResourceOwner owner, ResourceOwnerDeleteProc proc, void *arg)
+{
+	if (!owner)
+		return;
+	if (arg != owner->on_delete_arg)
+		return;
+	if (NULL != proc &&
+	    proc != owner->on_delete)
+		return;
+	owner->on_delete = NULL;
+	owner->on_delete_arg = NULL;
+}
+
 
 /*
  * Make sure there is room for at least one more entry in a ResourceOwner's
diff --git a/src/include/utils/portal.h b/src/include/utils/portal.h
index 4ae7e46..41492c6 100644
--- a/src/include/utils/portal.h
+++ b/src/include/utils/portal.h
@@ -205,6 +205,7 @@ extern void AtSubAbort_Portals(SubTransactionId mySubid,
 extern void AtSubCleanup_Portals(SubTransactionId mySubid);
 extern Portal CreatePortal(const char *name, bool allowDup, bool dupSilent);
 extern Portal CreateNewPortal(void);
+extern void PortalAllocResourceOwner(Portal portal);
 extern void PinPortal(Portal portal);
 extern void UnpinPortal(Portal portal);
 extern void MarkPortalDone(Portal portal);
diff --git a/src/include/utils/resowner.h b/src/include/utils/resowner.h
index da76649..9a06d88 100644
--- a/src/include/utils/resowner.h
+++ b/src/include/utils/resowner.h
@@ -58,6 +58,11 @@ typedef void (*ResourceReleaseCallback) (ResourceReleasePhase phase,
 													 bool isTopLevel,
 													 void *arg);
 
+/*
+ *	ResourceOwner delete procedure
+ */
+typedef void (*ResourceOwnerDeleteProc) (ResourceOwner owner, void *arg);
+
 
 /*
  * Functions in resowner.c
@@ -78,5 +83,7 @@ extern void RegisterResourceReleaseCallback(ResourceReleaseCallback callback,
 								void *arg);
 extern void UnregisterResourceReleaseCallback(ResourceReleaseCallback callback,
 								  void *arg);
+extern void RegisterResownerOnDeleteProc(ResourceOwner owner, ResourceOwnerDeleteProc proc, void *arg);
+extern void UnregisterResownerOnDeleteProc(ResourceOwner owner, ResourceOwnerDeleteProc proc, void *arg);
 
 #endif   /* RESOWNER_H */
