@@ -764,15 +764,14 @@ logical_read_xlog_page(XLogReaderState *state, XLogRecPtr targetPagePtr, int req
764764/* make sure we have enough WAL available */
765765flushptr = WalSndWaitForWal (targetPagePtr + reqLen );
766766
767- /* more than one block available */
768- if (targetPagePtr + XLOG_BLCKSZ <=flushptr )
769- count = XLOG_BLCKSZ ;
770- /* not enough WAL synced, that can happen during shutdown */
771- else if (targetPagePtr + reqLen > flushptr )
767+ /* fail if not (implies we are going to shut down) */
768+ if (flushptr < targetPagePtr + reqLen )
772769return -1 ;
773- /* part of the page available */
770+
771+ if (targetPagePtr + XLOG_BLCKSZ <=flushptr )
772+ count = XLOG_BLCKSZ ;/* more than one block available */
774773else
775- count = flushptr - targetPagePtr ;
774+ count = flushptr - targetPagePtr ;/* part of the page available */
776775
777776/* now actually read the data, we know it's there */
778777XLogRead (cur_page ,targetPagePtr ,XLOG_BLCKSZ );
@@ -1158,7 +1157,11 @@ WalSndWriteData(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId xid,
11581157}
11591158
11601159/*
1161- * Wait till WAL < loc is flushed to disk so it can be safely read.
1160+ * Wait till WAL < loc is flushed to disk so it can be safely sent to client.
1161+ *
1162+ * Returns end LSN of flushed WAL. Normally this will be >= loc, but
1163+ * if we detect a shutdown request (either from postmaster or client)
1164+ * we will return early, so caller must always check.
11621165 */
11631166static XLogRecPtr
11641167WalSndWaitForWal (XLogRecPtr loc )
@@ -1225,9 +1228,7 @@ WalSndWaitForWal(XLogRecPtr loc)
12251228RecentFlushPtr = GetXLogReplayRecPtr (NULL );
12261229
12271230/*
1228- * If postmaster asked us to stop, don't wait here anymore. This will
1229- * cause the xlogreader to return without reading a full record, which
1230- * is the fastest way to reach the mainloop which then can quit.
1231+ * If postmaster asked us to stop, don't wait anymore.
12311232 *
12321233 * It's important to do this check after the recomputation of
12331234 * RecentFlushPtr, so we can send all remaining data before shutting
@@ -1258,14 +1259,20 @@ WalSndWaitForWal(XLogRecPtr loc)
12581259WalSndCaughtUp = true;
12591260
12601261/*
1261- * Try to flush pending output to the client. Also wait for the socket
1262- * becoming writable, if there's still pending output after an attempt
1263- * to flush. Otherwise we might just sit on output data while waiting
1264- * for new WAL being generated.
1262+ * Try to flush any pending output to the client.
12651263 */
12661264if (pq_flush_if_writable ()!= 0 )
12671265WalSndShutdown ();
12681266
1267+ /*
1268+ * If we have received CopyDone from the client, sent CopyDone
1269+ * ourselves, and the output buffer is empty, it's time to exit
1270+ * streaming, so fail the current WAL fetch request.
1271+ */
1272+ if (streamingDoneReceiving && streamingDoneSending &&
1273+ !pq_is_send_pending ())
1274+ break ;
1275+
12691276now = GetCurrentTimestamp ();
12701277
12711278/* die if timeout was reached */
@@ -1274,6 +1281,13 @@ WalSndWaitForWal(XLogRecPtr loc)
12741281/* Send keepalive if the time has come */
12751282WalSndKeepaliveIfNecessary (now );
12761283
1284+ /*
1285+ * Sleep until something happens or we time out. Also wait for the
1286+ * socket becoming writable, if there's still pending output.
1287+ * Otherwise we might sit on sendable output data while waiting for
1288+ * new WAL to be generated. (But if we have nothing to send, we don't
1289+ * want to wake on socket-writable.)
1290+ */
12771291sleeptime = WalSndComputeSleeptime (now );
12781292
12791293wakeEvents = WL_LATCH_SET |WL_POSTMASTER_DEATH |
@@ -1282,7 +1296,6 @@ WalSndWaitForWal(XLogRecPtr loc)
12821296if (pq_is_send_pending ())
12831297wakeEvents |=WL_SOCKET_WRITEABLE ;
12841298
1285- /* Sleep until something happens or we time out */
12861299WaitLatchOrSocket (MyLatch ,wakeEvents ,
12871300MyProcPort -> sock ,sleeptime );
12881301}
@@ -1870,7 +1883,8 @@ WalSndLoop(WalSndSendDataCallback send_data)
18701883 * ourselves, and the output buffer is empty, it's time to exit
18711884 * streaming.
18721885 */
1873- if (!pq_is_send_pending ()&& streamingDoneSending && streamingDoneReceiving )
1886+ if (streamingDoneReceiving && streamingDoneSending &&
1887+ !pq_is_send_pending ())
18741888break ;
18751889
18761890/*