/* make sure we have enough WAL available */
    flushptr = WalSndWaitForWal(targetPagePtr + reqLen);
 
-   /* more than one block available */
-   if (targetPagePtr + XLOG_BLCKSZ <= flushptr)
-       count = XLOG_BLCKSZ;
-   /* not enough WAL synced, that can happen during shutdown */
-   else if (targetPagePtr + reqLen > flushptr)
+   /* fail if not (implies we are going to shut down) */
+   if (flushptr < targetPagePtr + reqLen)
        return -1;
-   /* part of the page available */
+
+   if (targetPagePtr + XLOG_BLCKSZ <= flushptr)
+       count = XLOG_BLCKSZ;    /* more than one block available */
    else
-       count = flushptr - targetPagePtr;
+       count = flushptr - targetPagePtr;   /* part of the page available */
 
    /* now actually read the data, we know it's there */
    XLogRead(cur_page, targetPagePtr, XLOG_BLCKSZ);
 }
 
 /*
- * Wait till WAL < loc is flushed to disk so it can be safely read.
+ * Wait till WAL < loc is flushed to disk so it can be safely sent to client.
+ *
+ * Returns end LSN of flushed WAL.  Normally this will be >= loc, but
+ * if we detect a shutdown request (either from postmaster or client)
+ * we will return early, so caller must always check.
  */
 static XLogRecPtr
 WalSndWaitForWal(XLogRecPtr loc)
            RecentFlushPtr = GetXLogReplayRecPtr(NULL);
 
        /*
-        * If postmaster asked us to stop, don't wait here anymore. This will
-        * cause the xlogreader to return without reading a full record, which
-        * is the fastest way to reach the mainloop which then can quit.
+        * If postmaster asked us to stop, don't wait anymore.
         *
         * It's important to do this check after the recomputation of
         * RecentFlushPtr, so we can send all remaining data before shutting
        WalSndCaughtUp = true;
 
        /*
-        * Try to flush pending output to the client. Also wait for the socket
-        * becoming writable, if there's still pending output after an attempt
-        * to flush. Otherwise we might just sit on output data while waiting
-        * for new WAL being generated.
+        * Try to flush any pending output to the client.
         */
        if (pq_flush_if_writable() != 0)
            WalSndShutdown();
 
+       /*
+        * If we have received CopyDone from the client, sent CopyDone
+        * ourselves, and the output buffer is empty, it's time to exit
+        * streaming, so fail the current WAL fetch request.
+        */
+       if (streamingDoneReceiving && streamingDoneSending &&
+           !pq_is_send_pending())
+           break;
+
        now = GetCurrentTimestamp();
 
        /* die if timeout was reached */
        /* Send keepalive if the time has come */
        WalSndKeepaliveIfNecessary(now);
 
+       /*
+        * Sleep until something happens or we time out.  Also wait for the
+        * socket becoming writable, if there's still pending output.
+        * Otherwise we might sit on sendable output data while waiting for
+        * new WAL to be generated.  (But if we have nothing to send, we don't
+        * want to wake on socket-writable.)
+        */
        sleeptime = WalSndComputeSleeptime(now);
 
        wakeEvents = WL_LATCH_SET | WL_POSTMASTER_DEATH |
        if (pq_is_send_pending())
            wakeEvents |= WL_SOCKET_WRITEABLE;
 
-       /* Sleep until something happens or we time out */
        WaitLatchOrSocket(MyLatch, wakeEvents,
                          MyProcPort->sock, sleeptime,
                          WAIT_EVENT_WAL_SENDER_WAIT_WAL);
         * ourselves, and the output buffer is empty, it's time to exit
         * streaming.
         */
-       if (!pq_is_send_pending() && streamingDoneSending && streamingDoneReceiving)
+       if (streamingDoneReceiving && streamingDoneSending &&
+           !pq_is_send_pending())
            break;
 
        /*