From f1a2f3a0c4ea51d9904fd30c9c11cb474312353b Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Fri, 3 Oct 2025 14:04:08 +0900 Subject: [PATCH] pgbench: Fail cleanly when finding a COPY result state Currently, pgbench aborts when a COPY response is received in readCommandResponse(). However, as PQgetResult() returns an empty result when there is no asynchronous result, through getCopyResult(), the logic done at the end of readCommandResponse() for the error path leads to an infinite loop. This commit forcefully exits the COPY state with PQendcopy() before moving to the error handler when fiding a COPY state, avoiding the infinite loop. The COPY protocol is not supported by pgbench anyway, as an error is assumed in this case, so giving up is better than having the tool be stuck forever. pgbench was interruptible in this state. A TAP test is added to check that an error happens if trying to use COPY. Author: Anthonin Bonnefoy Discussion: https://postgr.es/m/CAO6_XqpHyF2m73ifV5a=5jhXxH2chk=XrgefY+eWWPe2Eft3=A@mail.gmail.com Backpatch-through: 13 --- src/bin/pgbench/pgbench.c | 14 ++++++++++++++ src/bin/pgbench/t/001_pgbench_with_server.pl | 11 +++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c index 0712fbf6efc..565dcb3cd00 100644 --- a/src/bin/pgbench/pgbench.c +++ b/src/bin/pgbench/pgbench.c @@ -2817,6 +2817,20 @@ readCommandResponse(CState *st, MetaCommand meta, char *varprefix) /* otherwise the result is simply thrown away by PQclear below */ break; + case PGRES_COPY_IN: + case PGRES_COPY_OUT: + case PGRES_COPY_BOTH: + pg_log_error("COPY is not supported in pgbench, aborting"); + + /* + * We need to exit the copy state. Otherwise, PQgetResult() + * will always return an empty PGresult as an effect of + * getCopyResult(), leading to an infinite loop in the error + * cleanup done below. + */ + PQendcopy(st->con); + goto error; + default: /* anything else is unexpected */ pg_log_error("client %d script %d aborted in command %d query %d: %s", diff --git a/src/bin/pgbench/t/001_pgbench_with_server.pl b/src/bin/pgbench/t/001_pgbench_with_server.pl index a4a7afd64f5..a21dc2b37b9 100644 --- a/src/bin/pgbench/t/001_pgbench_with_server.pl +++ b/src/bin/pgbench/t/001_pgbench_with_server.pl @@ -1185,6 +1185,17 @@ pgbench( check_pgbench_logs($bdir, '001_pgbench_log_3', 1, 10, 10, qr{^0 \d{1,2} \d+ \d \d+ \d+$}); +# Test copy in pgbench +$node->pgbench( + '-t 10', + 2, + [], + [ qr{COPY is not supported in pgbench, aborting} ], + 'Test copy in script', + { + '001_copy' => q{ COPY pgbench_accounts FROM stdin } + }); + # done $node->safe_psql('postgres', 'DROP TABLESPACE regress_pgbench_tap_1_ts'); $node->stop; -- 2.47.3