diff --git a/src/backend/utils/resowner/resowner.c b/src/backend/utils/resowner/resowner.c
index 06e1121c5ff..03d2f5a0334 100644
--- a/src/backend/utils/resowner/resowner.c
+++ b/src/backend/utils/resowner/resowner.c
@@ -347,6 +347,7 @@ ResourceOwnerReleaseAll(ResourceOwner owner, ResourceReleasePhase phase,
 {
 	ResourceElem *items;
 	uint32		nitems;
+	bool		using_arr;
 
 	/*
 	 * ResourceOwnerSort must've been called already.  All the resources are
@@ -358,12 +359,14 @@ ResourceOwnerReleaseAll(ResourceOwner owner, ResourceReleasePhase phase,
 	{
 		items = owner->arr;
 		nitems = owner->narr;
+		using_arr = true;
 	}
 	else
 	{
 		Assert(owner->narr == 0);
 		items = owner->hash;
 		nitems = owner->nhash;
+		using_arr = false;
 	}
 
 	/*
@@ -392,13 +395,20 @@ ResourceOwnerReleaseAll(ResourceOwner owner, ResourceReleasePhase phase,
 			elog(WARNING, "resource was not closed: %s", res_str);
 			pfree(res_str);
 		}
-		kind->ReleaseResource(value);
+
+		/*
+		 * Update stored count to forget the item before calling its
+		 * ReleaseResource method.  This avoids double-free crashes in case an
+		 * error gets thrown within ReleaseResource.
+		 */
 		nitems--;
+		if (using_arr)
+			owner->narr = nitems;
+		else
+			owner->nhash = nitems;
+
+		kind->ReleaseResource(value);
 	}
-	if (owner->nhash == 0)
-		owner->narr = nitems;
-	else
-		owner->nhash = nitems;
 }
 
 
