Re: libpq async duplicate error results

Peter Eisentraut <peter.eisentraut@enterprisedb.com>

From: Peter Eisentraut <peter.eisentraut@enterprisedb.com>
To: Tom Lane <tgl@sss.pgh.pa.us>
Cc: Fabien COELHO <coelho@cri.ensmp.fr>, pgsql-hackers <pgsql-hackers@postgresql.org>
Date: 2022-02-03T14:10:14Z
Lists: pgsql-hackers
Tom, you worked on reorganzing the error message handling in libpq in 
PostgreSQL 14 (commit ffa2e4670123124b92f037d335a1e844c3782d3f).  Any 
thoughts on this?


On 25.01.22 09:32, Peter Eisentraut wrote:
> 
> This issue was discovered by Fabien in the SHOW_ALL_RESULTS thread.  I'm 
> posting it here separately, because I think it ought to be addressed in 
> libpq rather than with a workaround in psql, as proposed over there.
> 
> When using PQsendQuery() + PQgetResult() and the server crashes during 
> the execution of the command, PQgetResult() then returns two result sets 
> with partially duplicated error messages, like this from the attached 
> test program:
> 
> command = SELECT 'before';
> result 1 status = PGRES_TUPLES_OK
> error message = ""
> 
> command = SELECT pg_terminate_backend(pg_backend_pid());
> result 1 status = PGRES_FATAL_ERROR
> error message = "FATAL:  terminating connection due to administrator 
> command
> "
> result 2 status = PGRES_FATAL_ERROR
> error message = "FATAL:  terminating connection due to administrator 
> command
> server closed the connection unexpectedly
>      This probably means the server terminated abnormally
>      before or while processing the request.
> "
> 
> command = SELECT 'after';
> PQsendQuery() error: no connection to the server
> 
> 
> This is hidden in normal use because PQexec() throws away all but the 
> last result set, but the extra one is still generated internally.
> 
> Apparently, this has changed between PG13 and PG14.  In PG13 and 
> earlier, the output is
> 
> command = SELECT 'before';
> result 1 status = PGRES_TUPLES_OK
> error message = ""
> 
> command = SELECT pg_terminate_backend(pg_backend_pid());
> result 1 status = PGRES_FATAL_ERROR
> error message = "FATAL:  terminating connection due to administrator 
> command
> "
> result 2 status = PGRES_FATAL_ERROR
> error message = "server closed the connection unexpectedly
>      This probably means the server terminated abnormally
>      before or while processing the request.
> "
> 
> command = SELECT 'after';
> PQsendQuery() error: no connection to the server
> 
> In PG13, PQexec() concatenates all the error messages from multiple 
> results, so a user of PQexec() sees the same output before and after. 
> But for users of the lower-level APIs, things have become a bit more 
> confusing.
> 
> Also, why are there multiple results being generated in the first place?
> 
> 
> [0]: 
> https://www.postgresql.org/message-id/alpine.DEB.2.22.394.2112230703530.2668598@pseudo




Commits

  1. libpq: drop pending pipelined commands in pqDropConnection().

  2. Adjust interaction of libpq pipeline mode with errorMessage resets.

  3. Rearrange libpq's error reporting to avoid duplicated error text.

  4. In libpq, always append new error messages to conn->errorMessage.