public inbox for pgsql-hackers@postgresql.org
help / color / mirror / Atom feedFrom: Chao Li <li.evan.chao@gmail.com>
To: PostgreSQL-development <pgsql-hackers@postgresql.org>
Cc: Fujii Masao <masao.fujii@gmail.com>
Cc: vignesh C <vignesh21@gmail.com>
Subject: Set notice receiver before libpq connection startup
Date: Wed, 20 May 2026 15:21:08 +0800
Message-ID: <A2B8B7DE-C119-492F-A9FA-14CF86849777@gmail.com> (raw)
Hi,
While testing “Log remote NOTICE, WARNING, and similar messages using ereport()”, I noticed that libpqsrv_notice_receiver is only installed after libpqsrv_connect() finishes. As a result, NOTICE messages generated during connection establishment are missed by ereport() and are still printed to stderr.
To reproduce the issue, I created a separate database called remotedb and defined a login trigger that emits a NOTICE message:
```
CREATE DATABASE remotedb;
\c remotedb
CREATE OR REPLACE FUNCTION repro_login_notice()
RETURNS event_trigger
LANGUAGE plpgsql AS $$
BEGIN
RAISE NOTICE 'startup notice from remotedb login trigger';
END;
$$;
CREATE EVENT TRIGGER repro_login_notice_trg
ON login
EXECUTE FUNCTION repro_login_notice();
ALTER EVENT TRIGGER repro_login_notice_trg ENABLE ALWAYS;
```
Then, from another database:
```
evantest=# create extension dblink;
CREATE EXTENSION
evantest=# SELECT dblink_connect('host=127.0.0.1 port=5432 dbname=remotedb user=chaol sslmode=disable gssencmode=disable');
dblink_connect
----------------
OK
(1 row)
```
In the system log, the NOTICE message is printed directly:
```
2026-05-20 13:02:19.350 CST [24909] STATEMENT: SELECT dblink_connect('host=127.0.0.1 port=5432 dbname=remotedb user=chaol sslmode=disable gssencmode=disable');
NOTICE: startup notice from remotedb login trigger
```
To fix that, I think we should install libpqsrv_notice_receiver before libpqsrv_connect_internal(). In the attached patch, I added two helpers: libpqsrv_connect_with_notice_receiver() and libpqsrv_connect_params_with_notice_receiver().
With the fix, the NOTICE message now looks like this:
```
2026-05-20 14:44:49.296 CST [45567] LOG: received message via remote connection: NOTICE: startup notice from remotedb login trigger
2026-05-20 14:44:49.296 CST [45567] STATEMENT: SELECT dblink_connect('host=127.0.0.1 port=5432 dbname=remotedb user=chaol sslmode=disable gssencmode=disable');
```
Please see the attached patch for details.
Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/
Attachments:
[application/octet-stream] v1-0001-Set-notice-receiver-before-libpq-connection-start.patch (7.6K, 2-v1-0001-Set-notice-receiver-before-libpq-connection-start.patch)
download | inline diff:
From db52f5949884e57769b7ba7fc56be64c47ef1fa1 Mon Sep 17 00:00:00 2001
From: "Chao Li (Evan)" <lic@highgo.com>
Date: Wed, 20 May 2026 14:57:25 +0800
Subject: [PATCH v1] Set notice receiver before libpq connection startup
Some callers of libpqsrv_connect() and libpqsrv_connect_params()
install libpqsrv_notice_receiver after the connection has been
established. However, notices may also be received while
libpqsrv_connect_internal() is still processing the asynchronous
connection startup.
Add variants of these helpers that install a notice receiver immediately
after PQconnectStart() or PQconnectStartParams(), before entering
libpqsrv_connect_internal(). Use them in dblink, postgres_fdw, and
libpqwalreceiver, so notices emitted during connection startup are
handled in the same way as notices received after the connection is
established.
Author: Chao Li <lic@highgo.com>
Reviewed-by:
Discussion: https://postgr.es/m/
---
contrib/dblink/dblink.c | 15 ++++---
contrib/postgres_fdw/connection.c | 11 +++--
.../libpqwalreceiver/libpqwalreceiver.c | 11 +++--
src/include/libpq/libpq-be-fe-helpers.h | 42 ++++++++++++++-----
4 files changed, 49 insertions(+), 30 deletions(-)
diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index d843eee7e97..2093aef990f 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -222,7 +222,10 @@ dblink_get_conn(char *conname_or_str,
dblink_we_get_conn = WaitEventExtensionNew("DblinkGetConnect");
/* OK to make connection */
- conn = libpqsrv_connect(connstr, dblink_we_get_conn);
+ conn = libpqsrv_connect_with_notice_receiver(connstr,
+ dblink_we_get_conn,
+ libpqsrv_notice_receiver,
+ "received message via remote connection");
if (PQstatus(conn) == CONNECTION_BAD)
{
@@ -235,9 +238,6 @@ dblink_get_conn(char *conname_or_str,
errdetail_internal("%s", msg)));
}
- PQsetNoticeReceiver(conn, libpqsrv_notice_receiver,
- "received message via remote connection");
-
dblink_security_check(conn, NULL, connstr);
if (PQclientEncoding(conn) != GetDatabaseEncoding())
PQsetClientEncoding(conn, GetDatabaseEncodingName());
@@ -321,7 +321,9 @@ dblink_connect(PG_FUNCTION_ARGS)
}
/* OK to make connection */
- conn = libpqsrv_connect(connstr, dblink_we_connect);
+ conn = libpqsrv_connect_with_notice_receiver(connstr, dblink_we_connect,
+ libpqsrv_notice_receiver,
+ "received message via remote connection");
if (PQstatus(conn) == CONNECTION_BAD)
{
@@ -336,9 +338,6 @@ dblink_connect(PG_FUNCTION_ARGS)
errdetail_internal("%s", msg)));
}
- PQsetNoticeReceiver(conn, libpqsrv_notice_receiver,
- "received message via remote connection");
-
/* check password actually used if not superuser */
dblink_security_check(conn, connname, connstr);
diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c
index 3d2a8d0519d..0278f4a7cea 100644
--- a/contrib/postgres_fdw/connection.c
+++ b/contrib/postgres_fdw/connection.c
@@ -646,9 +646,11 @@ connect_pg_server(ForeignServer *server, UserMapping *user)
pgfdw_we_connect = WaitEventExtensionNew("PostgresFdwConnect");
/* OK to make connection */
- conn = libpqsrv_connect_params(keywords, values,
- false, /* expand_dbname */
- pgfdw_we_connect);
+ conn = libpqsrv_connect_params_with_notice_receiver(keywords, values,
+ false, /* expand_dbname */
+ pgfdw_we_connect,
+ libpqsrv_notice_receiver,
+ "received message via remote connection");
if (!conn || PQstatus(conn) != CONNECTION_OK)
ereport(ERROR,
@@ -657,9 +659,6 @@ connect_pg_server(ForeignServer *server, UserMapping *user)
server->servername),
errdetail_internal("%s", pchomp(PQerrorMessage(conn)))));
- PQsetNoticeReceiver(conn, libpqsrv_notice_receiver,
- "received message via remote connection");
-
/* Perform post-connection security checks. */
pgfdw_security_check(keywords, values, user, conn);
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 9f04c9ed25d..cc5f77d53f7 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -223,9 +223,11 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
conn = palloc0_object(WalReceiverConn);
conn->streamConn =
- libpqsrv_connect_params(keys, vals,
- /* expand_dbname = */ true,
- WAIT_EVENT_LIBPQWALRECEIVER_CONNECT);
+ libpqsrv_connect_params_with_notice_receiver(keys, vals,
+ /* expand_dbname = */ true,
+ WAIT_EVENT_LIBPQWALRECEIVER_CONNECT,
+ libpqsrv_notice_receiver,
+ "received message via replication");
if (options_val != NULL)
pfree(options_val);
@@ -245,9 +247,6 @@ libpqrcv_connect(const char *conninfo, bool replication, bool logical,
errhint("Target server's authentication method must be changed, or set password_required=false in the subscription parameters.")));
}
- PQsetNoticeReceiver(conn->streamConn, libpqsrv_notice_receiver,
- "received message via replication");
-
/*
* Set always-secure search path for the cases where the connection is
* used to run SQL queries, so malicious users can't get control.
diff --git a/src/include/libpq/libpq-be-fe-helpers.h b/src/include/libpq/libpq-be-fe-helpers.h
index 85d8b63f019..0571bb1fe50 100644
--- a/src/include/libpq/libpq-be-fe-helpers.h
+++ b/src/include/libpq/libpq-be-fe-helpers.h
@@ -43,6 +43,23 @@ static inline void libpqsrv_connect_internal(PGconn *conn, uint32 wait_event_inf
static inline PGresult *libpqsrv_get_result_last(PGconn *conn, uint32 wait_event_info);
static inline PGresult *libpqsrv_get_result(PGconn *conn, uint32 wait_event_info);
+static inline PGconn *
+libpqsrv_connect_with_notice_receiver(const char *conninfo,
+ uint32 wait_event_info,
+ PQnoticeReceiver proc, void *arg)
+{
+ PGconn *conn = NULL;
+
+ libpqsrv_connect_prepare();
+
+ conn = PQconnectStart(conninfo);
+ if (conn != NULL && proc != NULL)
+ PQsetNoticeReceiver(conn, proc, arg);
+
+ libpqsrv_connect_internal(conn, wait_event_info);
+
+ return conn;
+}
/*
* PQconnectdb() wrapper that reserves a file descriptor and processes
@@ -54,12 +71,24 @@ static inline PGresult *libpqsrv_get_result(PGconn *conn, uint32 wait_event_info
*/
static inline PGconn *
libpqsrv_connect(const char *conninfo, uint32 wait_event_info)
+{
+ return libpqsrv_connect_with_notice_receiver(conninfo, wait_event_info, NULL, NULL);
+}
+
+static inline PGconn *
+libpqsrv_connect_params_with_notice_receiver(const char *const *keywords,
+ const char *const *values,
+ int expand_dbname,
+ uint32 wait_event_info,
+ PQnoticeReceiver proc, void *arg)
{
PGconn *conn = NULL;
libpqsrv_connect_prepare();
- conn = PQconnectStart(conninfo);
+ conn = PQconnectStartParams(keywords, values, expand_dbname);
+ if (conn != NULL && proc != NULL)
+ PQsetNoticeReceiver(conn, proc, arg);
libpqsrv_connect_internal(conn, wait_event_info);
@@ -76,15 +105,8 @@ libpqsrv_connect_params(const char *const *keywords,
int expand_dbname,
uint32 wait_event_info)
{
- PGconn *conn = NULL;
-
- libpqsrv_connect_prepare();
-
- conn = PQconnectStartParams(keywords, values, expand_dbname);
-
- libpqsrv_connect_internal(conn, wait_event_info);
-
- return conn;
+ return libpqsrv_connect_params_with_notice_receiver(keywords, values, expand_dbname,
+ wait_event_info, NULL, NULL);
}
/*
--
2.50.1 (Apple Git-155)
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: li.evan.chao@gmail.com, masao.fujii@gmail.com, vignesh21@gmail.com
Subject: Re: Set notice receiver before libpq connection startup
In-Reply-To: <A2B8B7DE-C119-492F-A9FA-14CF86849777@gmail.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox