libpq: drop pending pipelined commands in pqDropConnection().
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 12 May 2022 16:42:29 +0000 (12:42 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 12 May 2022 17:08:31 +0000 (13:08 -0400)
The original coding did this in pqDropServerData(), which seems
fairly backwards.  Pending commands are more like already-queued
output data, which is dropped in pqDropConnection().  Moving the
operation means that we clear the command queue immediately upon
detecting connection drop, which improves the sanity of subsequent
behavior.  In particular this eliminates duplicated error message
text as a consequence of code added in b15f25446, which supposed
that a nonempty command queue must mean the prior operation is
still active.

There might be an argument for backpatching this to v14; but as with
b15f25446, I'm unsure about interactions with 618c16707.  For now,
given the lack of complaints about v14's behavior, leave it alone.

Per report from Peter Eisentraut.

Discussion: https://postgr.es/m/de57761c-b99b-3435-b0a6-474c72b1149a@enterprisedb.com

src/interfaces/libpq/fe-connect.c

index 4c12f1411f7d7c8f3327c63938d0fb57a0495784..6e936bbff301d2d3173a06a955bd536034d53cae 100644 (file)
@@ -377,6 +377,7 @@ static int  connectDBStart(PGconn *conn);
 static int     connectDBComplete(PGconn *conn);
 static PGPing internal_ping(PGconn *conn);
 static PGconn *makeEmptyPGconn(void);
+static void pqFreeCommandQueue(PGcmdQueueEntry *queue);
 static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions);
 static void freePGconn(PGconn *conn);
 static void closePGconn(PGconn *conn);
@@ -462,6 +463,12 @@ pqDropConnection(PGconn *conn, bool flushInput)
        /* Always discard any unsent data */
        conn->outCount = 0;
 
+       /* Likewise, discard any pending pipelined commands */
+       pqFreeCommandQueue(conn->cmd_queue_head);
+       conn->cmd_queue_head = conn->cmd_queue_tail = NULL;
+       pqFreeCommandQueue(conn->cmd_queue_recycle);
+       conn->cmd_queue_recycle = NULL;
+
        /* Free authentication/encryption state */
 #ifdef ENABLE_GSS
        {
@@ -569,12 +576,6 @@ pqDropServerData(PGconn *conn)
        }
        conn->notifyHead = conn->notifyTail = NULL;
 
-       pqFreeCommandQueue(conn->cmd_queue_head);
-       conn->cmd_queue_head = conn->cmd_queue_tail = NULL;
-
-       pqFreeCommandQueue(conn->cmd_queue_recycle);
-       conn->cmd_queue_recycle = NULL;
-
        /* Reset ParameterStatus data, as well as variables deduced from it */
        pstatus = conn->pstatus;
        while (pstatus != NULL)