diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index 490b121362..266cd64f6f 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -674,12 +674,7 @@ ProcessRepliesIfAny(void) int r; bool received = false; - /* - * If we already received a CopyDone from the frontend, any subsequent - * message is the beginning of a new command, and should be processed in - * the main processing loop. - */ - while (!streamingDoneReceiving) + for (;;) { r = pq_getbyte_if_available(&firstchar); if (r < 0) @@ -696,6 +691,19 @@ ProcessRepliesIfAny(void) break; } + /* + * If we already received a CopyDone from the frontend, the frontend + * should not send us anything until we've closed our end of the COPY. + * XXX: In theory, the frontend could already send the next command + * before receiving the CopyDone, but libpq doesn't currently allow + * that. + */ + if (streamingDoneReceiving && firstchar != 'X') + ereport(FATAL, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("unexpected standby message type \"%c\", after receiving CopyDone", + firstchar))); + /* Handle the very limited subset of commands expected in this phase */ switch (firstchar) { @@ -1048,10 +1056,8 @@ WalSndLoop(void) long sleeptime = 10000; /* 10 s */ int wakeEvents; - wakeEvents = WL_LATCH_SET | WL_POSTMASTER_DEATH | WL_TIMEOUT; - - if (!streamingDoneReceiving) - wakeEvents |= WL_SOCKET_READABLE; + wakeEvents = WL_LATCH_SET | WL_POSTMASTER_DEATH | WL_TIMEOUT | + WL_SOCKET_READABLE; if (pq_is_send_pending()) wakeEvents |= WL_SOCKET_WRITEABLE;