diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index c8223bf..c0d3622 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -487,6 +487,17 @@ static int
 CopyGetData(CopyState cstate, void *databuf, int minread, int maxread)
 {
 	int			bytesread = 0;
+	bool		old_ImmediateInterruptOK = ImmediateInterruptOK;
+
+	/*
+	 * For the duration of CopyGetData, we want to allow immediate
+	 * interrupts so that a shutdown can still occur even if the
+	 * client stalls in the middle of a COPY. This won't affect query
+	 * cancellation, because DoingCommandRead will still be true if in
+	 * the middle of receiving a message, which is important to avoid
+	 * protocol synchronization problems.
+	 */
+	ImmediateInterruptOK = true;
 
 	switch (cstate->copy_dest)
 	{
@@ -542,6 +553,7 @@ CopyGetData(CopyState cstate, void *databuf, int minread, int maxread)
 						case 'c':		/* CopyDone */
 							/* COPY IN correctly terminated by frontend */
 							cstate->fe_eof = true;
+							ImmediateInterruptOK = old_ImmediateInterruptOK;
 							return bytesread;
 						case 'f':		/* CopyFail */
 							ereport(ERROR,
@@ -578,6 +590,8 @@ CopyGetData(CopyState cstate, void *databuf, int minread, int maxread)
 			break;
 	}
 
+	ImmediateInterruptOK = old_ImmediateInterruptOK;
+
 	return bytesread;
 }
 
