> On Nov 12, 2025, at 17:34, Yugo Nagata <[email protected]> wrote: > > On Wed, 12 Nov 2025 00:20:15 +0900 > Fujii Masao <[email protected]> wrote: > >> On Tue, Nov 11, 2025 at 10:50 AM Yugo Nagata <[email protected]> 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 <[email protected]> > <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/
dirty-fix.diff
Description: Binary data
