Re: Suggestion to add --continue-client-on-abort option to pgbench
Chao Li <li.evan.chao@gmail.com>
From: Chao Li <li.evan.chao@gmail.com>
To: Yugo Nagata <nagata@sraoss.co.jp>,
Fujii Masao <masao.fujii@gmail.com>
Cc: Rintaro Ikeda <ikedarintarof@oss.nttdata.com>,
Jakub Wartak <jakub.wartak@enterprisedb.com>,
"Hayato Kuroda (Fujitsu)" <kuroda.hayato@fujitsu.com>,
"slpmcf@gmail.com" <slpmcf@gmail.com>,
"boekewurm+postgres@gmail.com" <boekewurm+postgres@gmail.com>,
"pgsql-hackers@postgresql.org" <pgsql-hackers@postgresql.org>,
Srinath Reddy Sadipiralla <srinath2133@gmail.com>,
Dilip Kumar <dilipbalaut@gmail.com>
Date: 2025-11-13T02:20:30Z
Lists: pgsql-hackers
Attachments
- dirty-fix.diff (application/octet-stream) patch
- (unnamed) (text/plain)
> On Nov 12, 2025, at 17:34, Yugo Nagata <nagata@sraoss.co.jp> wrote:
>
> On Wed, 12 Nov 2025 00:20:15 +0900
> Fujii Masao <masao.fujii@gmail.com> wrote:
>
>> On Tue, Nov 11, 2025 at 10:50 AM Yugo Nagata <nagata@sraoss.co.jp> wrote:
>>> I've attached a patch to fix this.
>>
>> Thanks for reporting the issue and providing the patch!
>>
>>> If a PGRES_PIPELINE_SYNC is followed by something other than PGRES_PIPELINE_SYNC or NULL,
>>> it means that another PGRES_PIPELINE_SYNC will eventually follow after some other results.
>>> In this case, we should reset the receive_sync flag and continue discarding results.
>>
>> Yes.
>>
>> + if (res)
>> + {
>> + received_sync = false;
>> + continue;
>>
>> Shouldn't we also call PQclear(res) here? For example:
>
> Thank you for your review!
> Yes, we need PQclear() here.
>
> I've attached an updated patch.
>
> The comment for the PQpipelineSync() call has been also updated to clarify
> why it is necessary.
>
> In addition, I added a connection status check in the loop to avoid an
> infinte loop that waiting for PQpipelineSync after a connection failure.
>
> I packed these changes in the same patch, but they can be split into separate
> patches.
>
> What do you think?
>
> Regards,
> Yugo Nagata
>
> --
> Yugo Nagata <nagata@sraoss.co.jp>
> <v2-0001-pgbench-Fix-assertion-failure-with-multiple-syncp.patch>
I debugged further this morning, and I think I have found the root cause. Ultimately, the problem is not with discardUntilSync(), instead, discardAvailableResults() mistakenly eats PGRES_PIPELINE_SYNC.
In my debug, I slightly updated Yugo’s script as: (every select returns a different value)
```
% cat pgbench_error.sql
\startpipeline
select 1/0;
\syncpipeline
select 2;
\syncpipeline
select 3;
\syncpipeline
select 4;
\endpipeline
```
Please see my dirty fix in the attachment. The diff is based master + Yugo’s v2 patch.
In my fix, I make discardAvailableResults() to return the PGRES_PIPELINE_SYNC it reads, and moved discardAvailableResults() out of getSQLErrorStatus(), so that if discardAvailableResults() returns a result, then use the result as next_res to continue the reading loop.
Here is my execution output:
```
% pgbench -n --failures-detailed --continue-on-error -M extended -t 5 -f pgbench_error.sql evantest
pgbench (19devel)
EVAN: readCommandResponse: Got result: res=7, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: discardAvailableResults: Got result: res=10, conn=0
EVAN: discardAvailableResults: Got sync, returning, conn=0
EVAN: readCommandResponse2: Got result: next_res=2, conn=0
EVAN: readCommandResponse2: Got next-result value: 2, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: readCommandResponse: completed, conn=0
EVAN: readCommandResponse: Got result: res=10, conn=0
EVAN: readCommandResponse2: Got result: next_res=2, conn=0
EVAN: readCommandResponse2: Got next-result value: 3, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: readCommandResponse: completed, conn=0
EVAN: readCommandResponse: Got result: res=10, conn=0
EVAN: readCommandResponse2: Got result: next_res=2, conn=0
EVAN: readCommandResponse2: Got next-result value: 4, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: readCommandResponse: completed, conn=0
EVAN: readCommandResponse: Got result: res=10, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: readCommandResponse: completed, conn=0
EVAN: readCommandResponse: Got result: res=7, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: discardAvailableResults: Got result: res=10, conn=0
EVAN: discardAvailableResults: Got sync, returning, conn=0
EVAN: readCommandResponse2: Got result: next_res=2, conn=0
EVAN: readCommandResponse2: Got next-result value: 2, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: readCommandResponse: completed, conn=0
EVAN: readCommandResponse: Got result: res=10, conn=0
EVAN: readCommandResponse2: Got result: next_res=2, conn=0
EVAN: readCommandResponse2: Got next-result value: 3, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: readCommandResponse: completed, conn=0
EVAN: readCommandResponse: Got result: res=10, conn=0
EVAN: readCommandResponse2: Got result: next_res=2, conn=0
EVAN: readCommandResponse2: Got next-result value: 4, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: readCommandResponse: completed, conn=0
EVAN: readCommandResponse: Got result: res=10, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: readCommandResponse: completed, conn=0
EVAN: readCommandResponse: Got result: res=7, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: discardAvailableResults: Got result: res=10, conn=0
EVAN: discardAvailableResults: Got sync, returning, conn=0
EVAN: readCommandResponse2: Got result: next_res=2, conn=0
EVAN: readCommandResponse2: Got next-result value: 2, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: readCommandResponse: completed, conn=0
EVAN: readCommandResponse: Got result: res=10, conn=0
EVAN: readCommandResponse2: Got result: next_res=2, conn=0
EVAN: readCommandResponse2: Got next-result value: 3, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: readCommandResponse: completed, conn=0
EVAN: readCommandResponse: Got result: res=10, conn=0
EVAN: readCommandResponse2: Got result: next_res=2, conn=0
EVAN: readCommandResponse2: Got next-result value: 4, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: readCommandResponse: completed, conn=0
EVAN: readCommandResponse: Got result: res=10, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: readCommandResponse: completed, conn=0
EVAN: readCommandResponse: Got result: res=7, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: discardAvailableResults: Got result: res=10, conn=0
EVAN: discardAvailableResults: Got sync, returning, conn=0
EVAN: readCommandResponse2: Got result: next_res=2, conn=0
EVAN: readCommandResponse2: Got next-result value: 2, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: readCommandResponse: completed, conn=0
EVAN: readCommandResponse: Got result: res=10, conn=0
EVAN: readCommandResponse2: Got result: next_res=2, conn=0
EVAN: readCommandResponse2: Got next-result value: 3, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: readCommandResponse: completed, conn=0
EVAN: readCommandResponse: Got result: res=10, conn=0
EVAN: readCommandResponse2: Got result: next_res=2, conn=0
EVAN: readCommandResponse2: Got next-result value: 4, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: readCommandResponse: completed, conn=0
EVAN: readCommandResponse: Got result: res=10, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: readCommandResponse: completed, conn=0
EVAN: readCommandResponse: Got result: res=7, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: discardAvailableResults: Got result: res=10, conn=0
EVAN: discardAvailableResults: Got sync, returning, conn=0
EVAN: readCommandResponse2: Got result: next_res=2, conn=0
EVAN: readCommandResponse2: Got next-result value: 2, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: readCommandResponse: completed, conn=0
EVAN: readCommandResponse: Got result: res=10, conn=0
EVAN: readCommandResponse2: Got result: next_res=2, conn=0
EVAN: readCommandResponse2: Got next-result value: 3, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: readCommandResponse: completed, conn=0
EVAN: readCommandResponse: Got result: res=10, conn=0
EVAN: readCommandResponse2: Got result: next_res=2, conn=0
EVAN: readCommandResponse2: Got next-result value: 4, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: readCommandResponse: completed, conn=0
EVAN: readCommandResponse: Got result: res=10, conn=0
EVAN: readCommandResponse2: Got result: next_res=7, conn=0
EVAN: readCommandResponse: completed, conn=0
transaction type: pgbench_error.sql
scaling factor: 1
query mode: extended
number of clients: 1
number of threads: 1
maximum number of tries: 1
number of transactions per client: 5
number of transactions actually processed: 5/5
number of failed transactions: 0 (0.000%)
number of serialization failures: 0 (0.000%)
number of deadlock failures: 0 (0.000%)
number of other failures: 0 (0.000%)
latency average = 0.265 ms
initial connection time = 2.092 ms
tps = 3773.584906 (without initial connection time)
```
You can see that, select 2/3/4 are properly handled.
Yugo-san, if you add some debug log, you will see that with your patch, 2 and 3 will be discarded by discardUntilSync(), so I don’t think your patch works.
To apply my dirty diff:
* git checkout master
* git am Yugo’s v2 patch
* git apply dirty-fix.diff
Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/
Commits
Same data as JSON:
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
pgbench: Fix assertion failure with multiple \syncpipeline in pipeline mode.
- 5bc251b28839 17.8 landed
- 00e64e35c8bd 18.2 landed
- 4aa0ac05765e 19 (unreleased) landed
-
pgbench: Add --continue-on-error option.
- 0ab208fa505c 19 (unreleased) landed
-
Fix "inconsistent DLL linkage" warning on Windows MSVC
- a3ea5330fcf4 19 (unreleased) cited
-
pgbench: Fix error reporting in readCommandResponse().
- 7d7e81d1e6b8 13.23 landed
- cb21e1f92fb3 14.20 landed
- bdccb6302871 15.15 landed
- 36c4d30c8f24 16.11 landed
- a912118c6055 17.7 landed
- 29aabbc43269 18.1 landed
- 19d4f9ffc207 19 (unreleased) landed
-
pgbench: Fix assertion failure with retriable errors in pipeline mode.
- 704f517711b4 15.15 landed
- 8b2e290bde21 16.11 landed
- f39d9164b70a 17.7 landed
- c736808e03b7 18.1 landed
- 8bb174295e89 19 (unreleased) landed
-
Allow pgbench to retry in some cases.
- 4a39f87acd6e 15.0 cited