From aec2add65853f2dca3cb138a524af8eb5c85f469 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@enterprisedb.com>
Date: Wed, 29 Mar 2017 17:30:46 +1300
Subject: [PATCH] Reject attempts to attach to a defunct DSA area.

As discovered by Andreas Seltenreich via sqlsmith, it is possible for a
late-starting parallel query worker to attach to the executor's DSA area
after all other backends have detached and it has already been destroyed,
leading to a second attempt to destroy it.  Detect and prevent this case
when attaching.

Thomas Munro

Discussion: http://postgr.es/m/CAEepm%3D2VvKCVXjg-REHTikoBUOhtfvfCyiJrT%3DzHDJyvMNd9pw%40mail.gmail.com
---
 src/backend/utils/mmgr/dsa.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/src/backend/utils/mmgr/dsa.c b/src/backend/utils/mmgr/dsa.c
index 6d5d12a6c9..d08317249b 100644
--- a/src/backend/utils/mmgr/dsa.c
+++ b/src/backend/utils/mmgr/dsa.c
@@ -1314,6 +1314,13 @@ attach_internal(void *place, dsm_segment *segment, dsa_handle handle)
 
 	/* Bump the reference count. */
 	LWLockAcquire(DSA_AREA_LOCK(area), LW_EXCLUSIVE);
+	if (control->refcnt == 0)
+	{
+		/* We can't attach to a DSA area that has already been destroyed. */
+		ereport(ERROR,
+				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+				 errmsg("could not attach to dsa_area")));
+	}
 	++control->refcnt;
 	LWLockRelease(DSA_AREA_LOCK(area));
 
-- 
2.12.2

