Revert "Cannot use WL_SOCKET_WRITEABLE without WL_SOCKET_READABLE."
authorJeff Davis <[email protected]>
Tue, 15 Dec 2020 07:47:30 +0000 (23:47 -0800)
committerJeff Davis <[email protected]>
Tue, 15 Dec 2020 07:47:30 +0000 (23:47 -0800)
This reverts commit 3a9e64aa0d96c8ffb6c682b082d0f72b1d373327.

Commit 4bad60e3 fixed the root of the problem that 3a9e64aa worked
around.

This enables proper pipelining of commands after terminating
replication, eliminating an undocumented limitation.

Discussion: https://postgr.es/m/3d57bc29-4459-578b-79cb-7641baf53c57%40iki.fi
Backpatch-through: 9.5

src/backend/replication/walsender.c

index 2eb19ad29369bee29c2d3b2be265f0ac04f684f7..d5c9bc31d8e7979a0466546e89c4e2b524091a29 100644 (file)
@@ -1719,7 +1719,12 @@ ProcessRepliesIfAny(void)
 
    last_processing = GetCurrentTimestamp();
 
-   for (;;)
+   /*
+    * 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)
    {
        pq_startmsgread();
        r = pq_getbyte_if_available(&firstchar);
@@ -1748,19 +1753,6 @@ ProcessRepliesIfAny(void)
            proc_exit(0);
        }
 
-       /*
-        * 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)
        {
@@ -2362,8 +2354,10 @@ WalSndLoop(WalSndSendDataCallback send_data)
            long        sleeptime;
            int         wakeEvents;
 
-           wakeEvents = WL_LATCH_SET | WL_EXIT_ON_PM_DEATH | WL_TIMEOUT |
-               WL_SOCKET_READABLE;
+           wakeEvents = WL_LATCH_SET | WL_EXIT_ON_PM_DEATH | WL_TIMEOUT;
+
+           if (!streamingDoneReceiving)
+               wakeEvents |= WL_SOCKET_READABLE;
 
            /*
             * Use fresh timestamp, not last_processing, to reduce the chance