From: | Arseniy Mukhin <arseniy(dot)mukhin(dot)dev(at)gmail(dot)com> |
---|---|
To: | Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us> |
Cc: | Noah Misch <noah(at)leadboat(dot)com>, Andres Freund <andres(at)anarazel(dot)de>, pgsql-hackers(at)postgresql(dot)org |
Subject: | Re: BackgroundPsql swallowing errors on windows |
Date: | 2025-09-27 18:39:07 |
Message-ID: | CAE7r3MJwj2hMmHK-Fv87uGRkHM4ZFhAMCMk+wciU8+T50iFLGA@mail.gmail.com |
Views: | Whole Thread | Raw Message | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
Hi,
I think I encountered the bug that relates to the patch from this
thread so I decided to write a report here.
version(): PostgreSQL 19devel on x86_64-linux, compiled by gcc-13.3.0,
64-bit. (master)
While writing a TAP test I noticed that background_psql hangs on a
simple query without any reason. The most simple reproducer I came up
with:
my $psql = $node->background_psql('postgres', timeout => 3);
$psql->query(q(\warn AAAAA));
$psql->query("select 1");
Here $psql->query("select 1;") hangs until timeout.
Here what I managed to understand after some investigation:
Just to remind how banner and banner_match look like:
my $banner = "background_psql: QUERY_SEPARATOR $query_cnt:";
my $banner_match = qr/(^|\n)$banner\r?\n/;
psql->query() hangs in an endless loop in pump_until() as the
termination condition (last if $$stream =~ /$until/) is never met.
Unfortunately, logs don't show the reason why we are stuck here (maybe
I do something wrong but it seems that [0] explains why pump_until()
timeout diag code doesn't work), so to get more information we need to
add some additional logging in pump_until(). If we add logging of
$$stream and $until then we can see next lines for pump_until() stderr
call:
STREAM: AAAAAbackground_psql: QUERY_SEPARATOR 2:
UNTIL: (?^:(^|\n)background_psql: QUERY_SEPARATOR 2:\r?\n)
STREAM here is what we have in stderr and UNTIL is just a banner_match.
You can see that we have stderr from the previous query ('AAAAA')
concatenated with the banner on the same line. So it doesn't match
what we have in $until pattern as it requires (^|\n) to be before the
banner. This way we have an endless loop. It seems that the reason we
don't have line separator after 'AAAAA' is a difference between how we
inject and remove the banner:
Here is a how we inject banner:
$self->{stdin} .= "$query\n;\n\\echo $banner\n\\warn $banner\n";
How we remove banner from stderr
$self->{stderr} =~ s/$banner_match//;
We remove from stderr not only the banner we previously injected with
warn, but also the line separator before the banner.
[0] https://www.postgresql.org/message-id/flat/1100715(dot)1712265845(at)sss(dot)pgh(dot)pa(dot)us
Best regards,
Arseniy Mukhin
From | Date | Subject | |
---|---|---|---|
Next Message | Amit Kapila | 2025-09-27 21:13:39 | Re: Proposal: Conflict log history table for Logical Replication |
Previous Message | Vik Fearing | 2025-09-27 18:14:58 | Re: [PATCH] GROUP BY ALL |