diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index fbc05f0dc13..cb1f3586d4c 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -917,15 +917,18 @@ ShmemResizeStruct(const char *name, Size new_size)
 	 * When shrinking, release memory pages beyond the new end, but not the
 	 * page containing maximal end of the structure, as it may be used by the
 	 * next structure.
-	 *
-	 * We do not consider the current end of the structure as it simplifies
-	 * the calculations. Instead we rely on the underlying APIs not to touch
-	 * the memory pages that will not be affected by the change in size.
 	 */
 	new_end = (char *) TYPEALIGN(page_size, (char *) result->location + new_size);
 	if (new_size < result->size)
 	{
-		char	   *max_end = (char *) TYPEALIGN_DOWN(page_size, (char *) result->location + result->maximum_size);
+		/*
+		 * Only pages currently RW should be freed; anything past result->size
+		 * is PROT_NONE reserved tail.  Also stop before the last page shared
+		 * with the next structure.
+		 */
+		char	   *current_end = (char *) TYPEALIGN(page_size, (char *) result->location + result->size);
+		char	   *reserved_end = (char *) TYPEALIGN_DOWN(page_size, (char *) result->location + result->maximum_size);
+		char	   *max_end = Min(current_end, reserved_end);
 
 		if (max_end > new_end)
 		{
