Fix bug in replication mode and snapshot isolation mode.
authorTatsuo Ishii <ishii@postgresql.org>
Fri, 9 Aug 2024 10:55:05 +0000 (19:55 +0900)
committerTatsuo Ishii <ishii@postgresql.org>
Fri, 9 Aug 2024 10:55:05 +0000 (19:55 +0900)
In replication mode and snapshot isolation mode when a command fishes,
pgpool waits for a ready for query message but forgot that some
commands (for example SET ROLE) produces a parameter status
message. As a result pgpool errors out that other message arrives
before the ready for query message.  Deal with the case when a
parameter status message arrives.

Here is the test case written in pgproto data format.

'P' "" "SET ROLE TO foo"
'B' "" "" 0 0 0
'E' "" 0
'P' "" "SELECT 1"
'B' "" "" 0 0 0
'E' "" 0
'S'
'Y'

Backpatch-through: v4.1.

src/protocol/pool_proto_modules.c

index 7725df65d38d9be884f90e61af396901aa661699..e62a3e0bf6494bdce0a8a48205a211ee880239df 100644 (file)
@@ -1480,9 +1480,31 @@ Parse(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * backend,
 
                        kind = pool_read_kind(backend);
                        if (kind != 'Z')
-                               ereport(ERROR,
-                                               (errmsg("unable to parse the query"),
-                                                errdetail("invalid read kind \"%c\" returned from backend %d after Sync message sent", kind, i)));
+                       {
+                               /*
+                                * It is possible that parameter status message was sent from
+                                * backend.
+                                */
+                               if (kind == 'S')
+                               {
+                                       if (ParameterStatus(frontend, backend) != POOL_CONTINUE)
+                                               ereport(ERROR,
+                                                               (errmsg("unable to process parameter status message")));
+
+                                       /* expecting ready for query message */
+                                       kind = pool_read_kind(backend);
+                                       if (kind != 'Z')
+                                               ereport(ERROR,
+                                                               (errmsg("unable to parse the query"),
+                                                                errdetail("invalid read kind \"%c\" returned from backend after Sync message sent",
+                                                                                  kind)));
+                               }
+                               else
+                                               ereport(ERROR,
+                                                               (errmsg("unable to parse the query"),
+                                                                errdetail("invalid read kind \"%c\" returned from backend after Sync message sent",
+                                                                                  kind)));
+                       }
 
                        /*
                         * SYNC message returns "Ready for Query" message.