commit 95d97c99785b8428f8c9f84c73d3e38711745607
Author: Chris Traverswq <chris.travers@gmail.com>
Date:   Thu Sep 6 12:09:08 2018 +0200

    Fix for race condition between startup process and parallel worker.
    
    THe startup process can send a SIGUSR1 signal every 5ms and this can cause
    the parallel worker to never complete the syscall that it continues to retry.
    
    THe fix checks for pending interrupts and addresses program flow accordingly,
    treating an incoming SIGUSR1, SIGTERM, and similar as subject to cleanup similar
    to an ENOSPC.

diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index 77e1bab54b..304726b5cf 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -47,6 +47,7 @@
  */
 
 #include "postgres.h"
+#include "miscadmin.h"
 
 #include <fcntl.h>
 #include <unistd.h>
@@ -330,10 +331,27 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
 			shm_unlink(name);
 		errno = save_errno;
 
+		/*
+		 * If we received a query cancel or termination signal, we will have
+		 * EINTR set here It may not be safe to handle interrupts here of this
+		 * sort so we just continue to the next point where it is.
+		 *
+		 * However, the safety of exceptions here are determined by the elevel
+		 * passed in by the function so if the elevel is ERROR or higher we
+		 * check for interrupts here if there is an EINTR errno raised by the
+		 * resize operation.  Otherwise we log the failure and move on to the
+		 * next point where interrupts are checked.  This allows for the
+		 * caller to handle cleanup and move to a safe point first.
+		 */
+		if (errno == EINTR && elevel >= ERROR)
+			CHECK_FOR_INTERRUPTS();
+
 		ereport(elevel,
 				(errcode_for_dynamic_shared_memory(),
 				 errmsg("could not resize shared memory segment \"%s\" to %zu bytes: %m",
 						name, request_size)));
+
+		/* This will throw appropriate errors for query cancel or termination */
 		return false;
 	}
 
@@ -419,11 +437,19 @@ dsm_impl_posix_resize(int fd, off_t size)
 #if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
 	if (rc == 0)
 	{
-		/* We may get interrupted, if so just retry. */
+		/*
+		 * We may get interrupted, if so just retry unless certain signals are
+		 * sent
+		 *
+		 * In rare cases it is possible for a signal loop to perpetually
+		 * pre-empt this call So where the signal would cause the query to
+		 * cancel or the process to terminate we exit the loop and return the
+		 * interrupted error to the caller who is now responsible for that.
+		 */
 		do
 		{
 			rc = posix_fallocate(fd, 0, size);
-		} while (rc == EINTR);
+		} while (rc == EINTR && !(ProcDiePending || QueryCancelPending));
 
 		/*
 		 * The caller expects errno to be set, but posix_fallocate() doesn't
