Thread
Commits
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
psql: Forbid use of COPY and \copy while in a pipeline
- 6e951f279bea 18.0 landed
-
psql: Abort connection when using \syncpipeline after COPY TO/FROM
- 7f3381c7ee66 18.0 landed
-
BUG #18944: Assertion Failure in psql with idle_session_timeout Set
PG Bug reporting form <noreply@postgresql.org> — 2025-06-02T06:34:12Z
The following bug has been logged on the website: Bug reference: 18944 Logged by: Nikita Kalinin Email address: n.kalinin@postgrespro.ru PostgreSQL version: 18beta1 Operating system: ubuntu 22.04 Description: Hello! When I execute the following query: psql <<EOF CREATE TABLE psql_pipeline(a INTEGER PRIMARY KEY, s TEXT); \startpipeline COPY psql_pipeline FROM STDIN; \syncpipeline \endpipeline EOF with `idle_session_timeout` set to, for example, 10000, I get the following error: FATAL: terminating connection due to idle-session timeout psql: common.c:1501: discardAbortedPipelineResults: Assertion `pset.available_results > 0' failed. [1] 1747708 abort (core dumped) psql <<<'' Coredump: #0 __pthread_kill_implementation (threadid=278301224788256, signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44 #1 0x0000fd1d0d757670 in __pthread_kill_internal (signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:78 #2 0x0000fd1d0d70cb3c in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26 #3 0x0000fd1d0d6f7e00 in __GI_abort () at ./stdlib/abort.c:79 #4 0x0000fd1d0d705cc0 in __assert_fail_base (fmt=0xfd1d0d82c770 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=assertion@entry=0xb9a5a2d96080 "pset.available_results > 0", file=file@entry=0xb9a5a2d95fa0 "common.c", line=line@entry=1501, function=function@entry=0xb9a5a2dc4138 <__PRETTY_FUNCTION__.3> "discardAbortedPipelineResults") at ./assert/assert.c:96 #5 0x0000fd1d0d705d30 in __assert_fail (assertion=assertion@entry=0xb9a5a2d96080 "pset.available_results > 0", file=file@entry=0xb9a5a2d95fa0 "common.c", line=line@entry=1501, function=function@entry=0xb9a5a2dc4138 <__PRETTY_FUNCTION__.3> "discardAbortedPipelineResults") at ./assert/assert.c:105 #6 0x0000b9a5a2d3ec10 in discardAbortedPipelineResults () at common.c:1501 #7 ExecQueryAndProcessResults (query=query@entry=0xb9a5bfbe5690 "COPY psql_pipeline FROM STDIN;", elapsed_msec=elapsed_msec@entry=0xffffe844e8a0, svpt_gone_p=svpt_gone_p@entry=0xffffe844e89f, is_watch=is_watch@entry=false, min_rows=min_rows@entry=0, opt=opt@entry=0x0, printQueryFout=printQueryFout@entry=0x0) at common.c:1828 #8 0x0000b9a5a2d3cc20 in SendQuery (query=0xb9a5bfbe5690 "COPY psql_pipeline FROM STDIN;") at common.c:1212 #9 0x0000b9a5a2d52c14 in MainLoop (source=source@entry=0xfd1d0d880880 <_IO_2_1_stdin_>) at mainloop.c:515 #10 0x0000b9a5a2d375b0 in process_file (filename=0x0, use_relative_path=use_relative_path@entry=false) at command.c:4870 #11 0x0000b9a5a2d31bc4 in main (argc=<optimized out>, argv=<optimized out>) at startup.c:420 It appears to be a continuation of this thread: https://www.postgresql.org/message-id/ebf6ce77-b180-4d6b-8eab-71f641499ddf@postgrespro.ru -- Nikita Kalinin Postgres Professional: http://www.postgrespro.com The Russian Postgres Company -
Re: BUG #18944: Assertion Failure in psql with idle_session_timeout Set
Michael Paquier <michael@paquier.xyz> — 2025-06-02T08:13:48Z
On Mon, Jun 02, 2025 at 06:34:12AM +0000, PG Bug reporting form wrote: > Hello! When I execute the following query: > psql <<EOF > CREATE TABLE psql_pipeline(a INTEGER PRIMARY KEY, s TEXT); > \startpipeline > COPY psql_pipeline FROM STDIN; > \syncpipeline > \endpipeline > EOF > with `idle_session_timeout` set to, for example, 10000, I get the following > error: > FATAL: terminating connection due to idle-session timeout > psql: common.c:1501: discardAbortedPipelineResults: Assertion > `pset.available_results > 0' failed. Reproduced here, thanks for the report. In this case, we are in a PGRES_FATAL_ERROR state due to the timeout triggered by the backend, and the loop discarding the results in discardAbortedPipelineResults() does not take into account this case scenario: we don't have a result to process yet, think that there is one, and kaboom. It seems to me that we should just add an extra case for the result = NULL case as there is nothing pending. A FATAL means that we need to give up anyway. Anthonin, what do you think? -- Michael
-
Re: BUG #18944: Assertion Failure in psql with idle_session_timeout Set
Anthonin Bonnefoy <anthonin.bonnefoy@datadoghq.com> — 2025-06-02T17:00:26Z
On Mon, Jun 2, 2025 at 10:13 AM Michael Paquier <michael@paquier.xyz> wrote: > Reproduced here, thanks for the report. In this case, we are in a > PGRES_FATAL_ERROR state due to the timeout triggered by the backend, > and the loop discarding the results in discardAbortedPipelineResults() > does not take into account this case scenario: we don't have a result > to process yet, think that there is one, and kaboom. It seems to me > that we should just add an extra case for the result = NULL case as > there is nothing pending. A FATAL means that we need to give up > anyway. > > Anthonin, what do you think? Also reproduced. On a cursory look (I should be able to dig into this deeper tomorrow), it seems like we're missing a ReadyForQuery response from the server. A sync message is normally answered by a ReadyForQuery which is translated to a PGRES_PIPELINE_SYNC in pqParseInput3. This is why we add the number of piped_syncs to the requested_results as we need to consume the generated PGRES_PIPELINE_SYNC with PQgetResult. With the \sendsync following a COPY, we have two Sync messages but only receive a single ReadyForQuery response. We have a similar issue running the following: \startpipeline COPY psql_pipeline FROM STDIN; \syncpipeline \endpipeline Enter data to be copied followed by a newline. End with a backslash and a period on a line by itself, or an EOF signal. >> COPY 0 The psql session gets stuck in PQgetResult as we're trying to read a sync response that doesn't exist. Looking at CopyGetData, it seems like Sync messages are consumed and ignored: case PqMsg_Sync: /* * Ignore Flush/Sync for the convenience of client * libraries (such as libpq) that may send those * without noticing that the command they just * sent was COPY. */ goto readmessage; So if that's expected, we may need additional logic to avoid increasing piped_syncs when we're after a COPY? On the other hand, ignoring the SYNC seems to break the protocol spec expectation that "there is one and only one ReadyForQuery sent for each Sync". -
Re: BUG #18944: Assertion Failure in psql with idle_session_timeout Set
Michael Paquier <michael@paquier.xyz> — 2025-06-02T23:31:16Z
On Mon, Jun 02, 2025 at 07:00:26PM +0200, Anthonin Bonnefoy wrote: > So if that's expected, we may need additional logic to avoid > increasing piped_syncs when we're after a COPY? On the other hand, > ignoring the SYNC seems to break the protocol spec expectation that > "there is one and only one ReadyForQuery sent for each Sync". Hmm. This stuff stands as it is in the backend COPY code since c01641f8aed0 from 2003, so there's not much we can do in the backend or libpq. Adding some specific logic in psql to avoid piped_syncs seems like the correct move seen from here. Most of that should be close to ExecQueryAndProcessResults(), don't you think? That's where we count the number of piped syncs. -- Michael
-
Re: BUG #18944: Assertion Failure in psql with idle_session_timeout Set
Anthonin Bonnefoy <anthonin.bonnefoy@datadoghq.com> — 2025-06-03T09:56:51Z
On Tue, Jun 3, 2025 at 1:31 AM Michael Paquier <michael@paquier.xyz> wrote: > Hmm. This stuff stands as it is in the backend COPY code since > c01641f8aed0 from 2003, so there's not much we can do in the backend > or libpq. Adding some specific logic in psql to avoid piped_syncs > seems like the correct move seen from here. > > Most of that should be close to ExecQueryAndProcessResults(), don't > you think? That's where we count the number of piped syncs. I've tried to adjust the piped syncs counter, but that's not enough. libpq's internal command queue still has the Syncs queued and will stay in a busy pipeline state if the backend doesn't send the expected ReadyForQuery. It could be possible to remove them from the queue with pqCommandQueueAdvance, but that would require psql to include libpq-int.h which is probably something we want to avoid. It doesn't seem like this case can be handled gracefully. The provided patch just aborts the connection from the frontend when excessive piped syncs are detected to avoid staying stuck in this inconsistent protocol state.
-
Re: BUG #18944: Assertion Failure in psql with idle_session_timeout Set
Michael Paquier <michael@paquier.xyz> — 2025-06-04T00:12:17Z
On Tue, Jun 03, 2025 at 11:56:51AM +0200, Anthonin Bonnefoy wrote: > I've tried to adjust the piped syncs counter, but that's not enough. > libpq's internal command queue still has the Syncs queued and will > stay in a busy pipeline state if the backend doesn't send the expected > ReadyForQuery. It could be possible to remove them from the queue with > pqCommandQueueAdvance, but that would require psql to include > libpq-int.h which is probably something we want to avoid. libpq-int.h is for internal purposes and should not be directly used in frontends, so that's a no-go. > It doesn't seem like this case can be handled gracefully. The provided > patch just aborts the connection from the frontend when excessive > piped syncs are detected to avoid staying stuck in this inconsistent > protocol state. I have been spending some time trying to get psql to gracefully handle this case, likely as you did by making ExecQueryAndProcessResults() fail gracefully, but even reinitializing the counters is not enough and I have also bumped into the libpq limitations. If somebody is excited enough to justify exposing these APIs, perhaps they'll have a good reason and a case to do so, but I'm not excited about doing that for this psql tooling: we are still able to serialize commands within a pipeline anyway. For now I have applied your patch, adding one extra test with COPY TO on top of the one with COPY FROM. -- Michael
-
Re: BUG #18944: Assertion Failure in psql with idle_session_timeout Set
Никита Калинин <n.kalinin@postgrespro.ru> — 2025-06-11T03:58:32Z
Hello! I do not believe it is necessary to create a new bug report, as, in my opinion, this issue remains a continuation of BUG #18944. Upon executing the following request: psql <<EOF CREATE TABLE psql_pipeline(a INTEGER PRIMARY KEY, s TEXT); \startpipeline COPY psql_pipeline FROM STDIN; \flushrequest \getresults \endpipeline \. COPY psql_pipeline FROM STDIN; \syncpipeline \getresults EOF we encounter yet another assertion failure: ERROR: invalid input syntax for type integer: "endpipeline" CONTEXT: COPY psql_pipeline, line 1, column a: "endpipeline" message type 0x5a arrived from server while idle Pipeline aborted, command did not run psql: common.c:1527: discardAbortedPipelineResults: Assertion `res == ((void *)0) || result_status == PGRES_PIPELINE_ABORTED' failed. Aborted (core dumped). Coredump: #0 __pthread_kill_implementation (threadid=255760382287552, signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44 #1 0x0000e89cda8b7670 in __pthread_kill_internal (signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:78 #2 0x0000e89cda86cb3c in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26 #3 0x0000e89cda857e00 in __GI_abort () at ./stdlib/abort.c:79 #4 0x0000e89cda865cc0 in __assert_fail_base ( fmt=0xe89cda98c770 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=assertion@entry=0xbd8dd0c47fd0 "res == ((void *)0) || result_status == PGRES_PIPELINE_ABORTED", file=file@entry=0xbd8dd0c47eb0 "common.c", line=line@entry=1527, function=function@entry=0xbd8dd0c76068 <__PRETTY_FUNCTION__.3> "discardAbortedPipelineResults") at ./assert/assert.c:96 #5 0x0000e89cda865d30 in __assert_fail ( assertion=assertion@entry=0xbd8dd0c47fd0 "res == ((void *)0) || result_status == PGRES_PIPELINE_ABORTED", file=file@entry=0xbd8dd0c47eb0 "common.c", line=line@entry=1527, function=function@entry=0xbd8dd0c76068 <__PRETTY_FUNCTION__.3> "discardAbortedPipelineResults") at ./assert/assert.c:105 #6 0x0000bd8dd0bfe6a8 in discardAbortedPipelineResults () at common.c:1527 #7 ExecQueryAndProcessResults (query=query@entry=0xbd8df7065330 "COPY psql_pipeline FROM STDIN;", elapsed_msec=elapsed_msec@entry=0xffffd1a532e0, svpt_gone_p=svpt_gone_p@entry=0xffffd1a532df, is_watch=is_watch@entry=false, min_rows=min_rows@entry=0, opt=opt@entry=0x0, printQueryFout=printQueryFout@entry=0x0) at common.c:1828 #8 0x0000bd8dd0bfc6d0 in SendQuery (query=0xbd8df7065330 "COPY psql_pipeline FROM STDIN;") at common.c:1212 #9 0x0000bd8dd0c10d3c in MainLoop (source=source@entry=0xe89cda9e0880 <_IO_2_1_stdin_>) at mainloop.c:515 #10 0x0000bd8dd0bf7070 in process_file (filename=0x0, use_relative_path=use_relative_path@entry=false) at command.c:4870 #11 0x0000bd8dd0bf1b04 in main (argc=<optimized out>, argv=<optimized out>) at startup.c:420 Nikita Kalinin Postgres Professional: http://www.postgrespro.com <http://www.postgrespro.com/> The Russian Postgres Company > On 4 Jun 2025, at 07:12, Michael Paquier <michael@paquier.xyz> wrote: > > On Tue, Jun 03, 2025 at 11:56:51AM +0200, Anthonin Bonnefoy wrote: >> I've tried to adjust the piped syncs counter, but that's not enough. >> libpq's internal command queue still has the Syncs queued and will >> stay in a busy pipeline state if the backend doesn't send the expected >> ReadyForQuery. It could be possible to remove them from the queue with >> pqCommandQueueAdvance, but that would require psql to include >> libpq-int.h which is probably something we want to avoid. > > libpq-int.h is for internal purposes and should not be directly > used in frontends, so that's a no-go. > >> It doesn't seem like this case can be handled gracefully. The provided >> patch just aborts the connection from the frontend when excessive >> piped syncs are detected to avoid staying stuck in this inconsistent >> protocol state. > > I have been spending some time trying to get psql to gracefully handle > this case, likely as you did by making ExecQueryAndProcessResults() > fail gracefully, but even reinitializing the counters is not enough > and I have also bumped into the libpq limitations. If somebody is > excited enough to justify exposing these APIs, perhaps they'll have a > good reason and a case to do so, but I'm not excited about doing that > for this psql tooling: we are still able to serialize commands within > a pipeline anyway. > > For now I have applied your patch, adding one extra test with COPY TO > on top of the one with COPY FROM. > -- > Michael -
Re: BUG #18944: Assertion Failure in psql with idle_session_timeout Set
Anthonin Bonnefoy <anthonin.bonnefoy@datadoghq.com> — 2025-06-11T14:11:14Z
On Wed, Jun 11, 2025 at 5:58 AM Никита Калинин <n.kalinin@postgrespro.ru> wrote: > > I do not believe it is necessary to create a new bug report, as, in my opinion, this issue remains a continuation of BUG #18944. Upon executing the following request: > > psql <<EOF > CREATE TABLE psql_pipeline(a INTEGER PRIMARY KEY, s TEXT); > \startpipeline > COPY psql_pipeline FROM STDIN; > \flushrequest > \getresults > \endpipeline > \. > COPY psql_pipeline FROM STDIN; > \syncpipeline > \getresults > EOF > > we encounter yet another assertion failure: > > ERROR: invalid input syntax for type integer: "endpipeline" > CONTEXT: COPY psql_pipeline, line 1, column a: "endpipeline" > message type 0x5a arrived from server while idle > Pipeline aborted, command did not run > psql: common.c:1527: discardAbortedPipelineResults: Assertion `res == ((void *)0) || result_status == PGRES_PIPELINE_ABORTED' failed. I've managed to reproduce, thanks for the report. The issue seems to come from COPY automatically sending a Sync message. During the first COPY failure, the sync is used as a synchronisation point, aborts the transaction and is ready to process new commands from the client. However, from the client's point of view, the pipeline is in an aborted state and all commands should be ignored as ignore_till_sync should be true.However, that's not the case due to the Sync message automatically added by COPY. Thus, when the second COPY is sent (something else than COPY can trigger this), we go through discardAbortedPipelineResults while the server answers to the commands, triggering the assertion failure. Libpq's fe-exec doesn't seem to handle a possible pipeline state in PQputCopyEnd. Naively, I've tried to only send a Sync message if 'conn->pipelineStatus == PQ_PIPELINE_OFF' but this will block the client in Copy mode and the Sync message is needed to exit it. I didn't have time to look into this further today but a possible fix could be to send the Sync message and add it to the command queue if we're in a pipeline. This should allow libpq's state to get out of the aborted pipeline state and match the backend's state.
-
Re: BUG #18944: Assertion Failure in psql with idle_session_timeout Set
Michael Paquier <michael@paquier.xyz> — 2025-06-11T22:34:52Z
On Wed, Jun 11, 2025 at 04:11:14PM +0200, Anthonin Bonnefoy wrote: > Libpq's fe-exec doesn't seem to handle a possible pipeline state in > PQputCopyEnd. Naively, I've tried to only send a Sync message if > 'conn->pipelineStatus == PQ_PIPELINE_OFF' but this will block the > client in Copy mode and the Sync message is needed to exit it. > I didn't have time to look into this further today but a possible fix > could be to send the Sync message and add it to the command queue if > we're in a pipeline. This should allow libpq's state to get out of the > aborted pipeline state and match the backend's state. Hmm. The root issue is that we are trying to work around the limitations of the existing result handling required by COPY and the extended protocol which are both not interacting nicely as psql has little idea that we are in a COPY state because we've sent a plain COPY query (contrary to \copy, actually, where we could detect that with a counter). As this is the first release where these pipeline meta-commands exist, we may want to consider a more restrictive measure to prevent this state to happen to begin with, rather to try to implement workarounds. I understand that it may not be the best thing to do, but we could restrict the use of COPY in pipelines for the initial release of this feature and just say that we don't support it for now. Then, in the future, if somebody is interested, we could study how it is possible to lift this restriction, but I suspect that we won't fly high without some redesign of libpq in terms if pipeline queues, which has the risk of introducing juicy bugs, but that would be a problem of the future. So my point would be to take a drastic decision in ExecQueryAndProcessResults() if we detect a PGRES_COPY_BOTH, PGRES_COPY_OUT or PGRES_COPY_IN while in a pipeline, and just give up. It does not prevent the feature to work for other queries, and we still have test coverage for queries that cannot run in transaction blocks like REINDEX CONCURRENTLY, etc. It just means that we cannot enter in a COPY state while in a pipeline. -- Michael
-
Re: BUG #18944: Assertion Failure in psql with idle_session_timeout Set
Anthonin Bonnefoy <anthonin.bonnefoy@datadoghq.com> — 2025-06-12T07:38:41Z
On Thu, Jun 12, 2025 at 12:35 AM Michael Paquier <michael@paquier.xyz> wrote: > So my point would be to take a drastic decision in > ExecQueryAndProcessResults() if we detect a PGRES_COPY_BOTH, > PGRES_COPY_OUT or PGRES_COPY_IN while in a pipeline, and just give up. > It does not prevent the feature to work for other queries, and we > still have test coverage for queries that cannot run in transaction > blocks like REINDEX CONCURRENTLY, etc. It just means that we cannot > enter in a COPY state while in a pipeline. Agreed, I've also contemplated this option given the amount of edge cases there are along with the limited usefulness of doing COPY within a pipeline. In a sense, this worked as a way to show the missing bits of libpq's pipeline support with COPY. The attached patch now aborts the connection anytime we enter COPY state while within a pipeline and removes all pipeline+COPY from the SQL tests.
-
Re: BUG #18944: Assertion Failure in psql with idle_session_timeout Set
Michael Paquier <michael@paquier.xyz> — 2025-06-12T08:03:27Z
On Thu, Jun 12, 2025 at 09:38:41AM +0200, Anthonin Bonnefoy wrote: > The attached patch now aborts the connection anytime we enter COPY > state while within a pipeline and removes all pipeline+COPY from the > SQL tests. Thanks for the patch, that's exactly what I was testing today, as a simple way to handle the problem reported. I'll check that in more details tomorrow, running a bit out of time today.. Do you think that it is worth adding a sentence about this restriction in the docs in the section dedicated to the pipeline meta-commands? We could just add a simple sentence like "<command>COPY</command> command is not supported while in pipeline mode." -- Michael
-
Re: BUG #18944: Assertion Failure in psql with idle_session_timeout Set
Anthonin Bonnefoy <anthonin.bonnefoy@datadoghq.com> — 2025-06-12T13:04:05Z
On Thu, Jun 12, 2025 at 10:03 AM Michael Paquier <michael@paquier.xyz> wrote: > Do you think that it is worth adding a sentence about this restriction > in the docs in the section dedicated to the pipeline meta-commands? > We could just add a simple sentence like "<command>COPY</command> > command is not supported while in pipeline mode." Good point, I've added the doc change to the patch.
-
Re: BUG #18944: Assertion Failure in psql with idle_session_timeout Set
Michael Paquier <michael@paquier.xyz> — 2025-06-13T01:19:44Z
On Thu, Jun 12, 2025 at 03:04:05PM +0200, Anthonin Bonnefoy wrote: > Good point, I've added the doc change to the patch. Thanks. I've tweaked the comments, fixing some grammar mistakes in them, and adjusted the tests a bit, then applied the result to close the door to all the problems reported. -- Michael