pg.ddx.io  pgsql-bugs@postgresql.org mailing list archive  
help / color / mirror / Atom feed
From: PG Bug reporting form <noreply@postgresql.org>
To: pgsql-bugs@lists.postgresql.org
Cc: i.trofimow@yandex.ru
Subject: BUG #17948: libpq seems to misbehave in a pipelining corner case
Date: Fri, 26 May 2023 17:27:39 +0000
Message-ID: <17948-fcace7557e449957@postgresql.org> (raw)

The following bug has been logged on the website:

Bug reference:      17948
Logged by:          Ivan Trofimov
Email address:      i.trofimow@yandex.ru
PostgreSQL version: 15.3
Operating system:   Ubuntu 20.04
Description:        

As far as i understand, there is an invariant in libpq, that if
PQpipelineSync call finished successfully,
PQresultStatus will eventually return PGRES_PIPELINE_SYNC, or the connection
will be in CONNECTION_BAD state.
 
This is highlighted in several places in the docs:
1. "PGRES_PIPELINE_SYNC is reported exactly once for each PQpipelineSync at
the corresponding point in the pipeline."
2. "From the client's perspective, after PQresultStatus returns
PGRES_FATAL_ERROR, the pipeline is flagged as aborted. 
PQresultStatus will report a PGRES_PIPELINE_ABORTED result for each
remaining queued operation in an aborted pipeline. 
The result for PQpipelineSync is reported as PGRES_PIPELINE_SYNC to signal
the end of the aborted pipeline and 
resumption of normal result processing. The client must process results with
PQgetResult during error recovery."
 
So i expect a code like this
 
if (!PQpipelineSync(conn)) exit(1);
 
while (PQstatus(conn) != CONNECTION_BAD) {
   res = PQgetResult(conn);
   if (PQresultStatus(res) == PGRES_PIPELINE_SYNC) {
       break;
   }
}
 
to eventually exit the loop.
 
However, if instead of expected "ReadyToQuery" response server sends an
error and closes the connection (
say, backend terminated by administrator or with a proxy in place and
upstream PG server being dead) this loop
gets stuck in busy-loop.
 
My understanding is that transitions in pipelining state-machine go like
this:
1. Initial PQgetResult call gets here
https://github.com/postgres/postgres/blob/a817edbf6f302c376f5c0012d19a0474b6bdea88/src/interfaces/li...
2. parseInput gets an error the server send
https://github.com/postgres/postgres/blob/a817edbf6f302c376f5c0012d19a0474b6bdea88/src/interfaces/li...

and switches the state into PGASYNC_READY
3. PQgetResult continues and here
https://github.com/postgres/postgres/blob/a817edbf6f302c376f5c0012d19a0474b6bdea88/src/interfaces/li...
advances the queue, so the Sync entry is gone, and switches into
PGASYNC_PIPELINE_IDLE later.
4. Next PQgetResult call gets here
https://github.com/postgres/postgres/blob/a817edbf6f302c376f5c0012d19a0474b6bdea88/src/interfaces/li...,
and pqPipelineProcessQueue switches into PGASYNC_IDLE here
https://github.com/postgres/postgres/blob/a817edbf6f302c376f5c0012d19a0474b6bdea88/src/interfaces/li...
 
Now we are stuck in the position where libpq considers the connection being
in CONNECTION_OK state 
(because no reads over half-closed socket have been issues), 
asyncStatus being PGASYNC_IDLE, pipeline being in PQ_PIPELINE_ABORTED state,

and the expected PGRES_PIPELINE_SYNC never came and never will (because
PGASYNC_IDLE, so PQgetResult returns NULL right away).

I am able to reproduce this behavior reliably via
https://pastebin.com/raw/4j3v3QzC,
linking against libpq5=15.3 and running the program against PostgreSQL
15.2.

Who is at fault here, is it libpq or me misunderstanding/misusing libpq?



view thread (6+ messages)  latest in thread

Message-ID: <17948-fcace7557e449957@postgresql.org>
Permalink:  ../17948-fcace7557e449957@postgresql.org/
Also on:    postgresql.org/message-id/17948-fcace7557e449957@postgresql.org

 · 

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: pgsql-bugs@postgresql.org
  Cc: noreply@postgresql.org, pgsql-bugs@lists.postgresql.org, i.trofimow@yandex.ru
  Subject: Re: BUG #17948: libpq seems to misbehave in a pipelining corner case
  In-Reply-To: <17948-fcace7557e449957@postgresql.org>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox