Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wQO8L-001WdY-2H for pgsql-hackers@arkaria.postgresql.org; Fri, 22 May 2026 11:33:42 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wQO8I-00D23g-0Y for pgsql-hackers@arkaria.postgresql.org; Fri, 22 May 2026 11:33:39 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wQO8H-00D23X-1h for pgsql-hackers@lists.postgresql.org; Fri, 22 May 2026 11:33:38 +0000 Received: from mail-qk1-x72a.google.com ([2607:f8b0:4864:20::72a]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wQO8F-00000000GOo-3iff for pgsql-hackers@postgresql.org; Fri, 22 May 2026 11:33:37 +0000 Received: by mail-qk1-x72a.google.com with SMTP id af79cd13be357-90b2fcf90a0so998812685a.1 for ; Fri, 22 May 2026 04:33:35 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1779449615; cv=none; d=google.com; s=arc-20240605; b=GziwhTheKqWYgK3UEn1mmaSYSvAZkNKV943HNZ57sA6oLUll8tH4EuI5JLS+oMSEk5 QOuiKB10cVi95yM9v3N4tltEZidheuslJa1ZNiBDKGKy5eyZC2My849UzdqeeHUaUz3b pnEZLJ/BIilsBfQQ6TNHfWLKeGCzGmmaGSN291VSRG/xk/DOAIygQnqkZQe7xX+aMUlc C4Z8Pbav8hBpk7VsohJKNYDUNt/9nzDee0ENX+D9EWz1w63SuJ4jUO5uMYUQkXqddBfS cxgIFaaCWnToLFPnhn6XamN5ZXNjR6VQ0v2/3mLuBPxCX5LOaf/f/mc47LV6btkPRfNI slPQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=dvJe59rbW4wyoiUvfII5aLInx58eifNvI5x27nPhByM=; fh=P0M5MjDn0U+RvAspZ6ZKnwOv4i5iUde6xmpV1gxUOo4=; b=h7M3v5/P0SZwUVp/FyaDMZmHEmEFZg1KMO4LnlLLQWzxcu+WOOLM8Q3B8k4RbgD+NC A8JKYqdW8k6C9G+0x6+mGpD4J+UFinlSFo1pm62XGFqdc+C8t7otGOXz1FC5oWjHG75v xt/PFiL8W28Yt9pjEKjyLPzj2NxTgE+TwVaz9qApBthOFV/bsAyGS8MxLouONvZKoHgO SMiDaagSJFskOzEvtJLLZ1iEA6L3Sk9bynnadMMQrwx4bdMrQYyfoTyP/cUK2zUM9OiE 38pqR4c70QcohOi5cixnQ8FiuWdRMQRA3Np7xC9XE9jt2c9Em2/oTmdmEd6uz8s4gbA1 u6NQ==; darn=postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779449615; x=1780054415; darn=postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=dvJe59rbW4wyoiUvfII5aLInx58eifNvI5x27nPhByM=; b=JLqJGOZePCYk0gGQWpXWFXeIhMEDAvhyMFok8f+HYx0XXaGZ3rrsPs1vnDUbdU/ouw Xy1vHf5MGgqSNQqjgeCWkoPMRdxD01WPrx4TnroVAnM979U1f6+eCA2JKXlOBSNXaczP gjq8yTQhw22PI6O3DWowXGSfGw01LTmZQW0rgy6ATkyDi9NNbAgdiU8oBmPpVfrTF2rE 2daNmmjMfOzLwgUCy5tTyfdIEZH7NI3oM+rcbR8JoBwwcHfaCAP9qTS+hooSVBJRjOfG 631O9o8Fil5PDMM9PNKMVCFH7Wezajq5eRBxDG32amlaziXboW+yxwEcdhflXdOSvhUC x+tg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779449615; x=1780054415; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=dvJe59rbW4wyoiUvfII5aLInx58eifNvI5x27nPhByM=; b=GvDfJXtrUorw5sXNrLRFMhcTy4jcLtO/3R6HsK8xyRI7lpoW5KD2i9Dc2IqLrFF+nR Amv5UgtrYv8NECPAgtRWdWCesmY16apfe5aq8DMgLd1dg8Ok0gnlrcHRPmn5zILxqylG sBYTbKMbqQL0f0en2TO8+iPpx+An1fAZff+frKkRAf5L+ayQb121r5n5+mOLLh9hO+Kn MMKMXmy4Y4GhtUGwYE0iHEvT0UaTHstDP+JAFWGAQURHhK59QTJgaV3ctnvPApRgoDYi i4hXcSz3UwheWVP+7xAgCkFtbjBSsB7PdyBPEENherLSvWXYBnABR0CIKOfkcMmqBEvW YNOw== X-Forwarded-Encrypted: i=1; AFNElJ/szOO7GTqeyZjK4vUqs6DepCBliIsFVo+LP6jkreYZdkgWt9Hay13+43Y7KwNSsLXt97gKdjqYB9stMImv@postgresql.org X-Gm-Message-State: AOJu0YwVYLDc8/a+IDfZXMCuXJ9QBzOUC/9K3K5xCGwPtHJXmUIReDtW NNUFixCF7lbqgLwdaIKrqUv+L/tW3siqTLGpNlw0Idh+IZQABUg6I8vbsAgjrHCVZNAwBYxaqzJ rbQou9vI73UqkwBoTfWfqT9h6kpN+8yU= X-Gm-Gg: Acq92OHLsopEMOQVOUYeIoN+cObMABAm16gml/swox+/2On+j0bIRQAAOTdCVqgheZg Oh92cxAWyTacEeI7vgRNNWKBZumrZXEj+InC1t6uWiyhor6Gt7/XWtP6Eoq6wDMZPWAOl7Vv3vu qUvcvNNktKv2CoXmLWyGvvcHdcpPLPAG/goEt5MQiJHmqq0JcgNX2pn1jvGGeI52bD/JpeaiWXc kg0Ue62W8IsWPnmm5l9tDEtVkCrXI9BzQJ9BitBvXVBdPNPHpf3ZSP1qhUhEGiDY9bx2UFfSzdI i0z5GV2JwzJ3gg4F4Tiq0x3EY2Yc08xsszZORYNbU3i9E1JgZdw/ILv3O4EuE5k+r+13sw2gj+U wzpW4v/uSKwc1+8u9Tu+D57S0u2QaPWu5i2v6Wg== X-Received: by 2002:a05:620a:199e:b0:8f8:d17c:9f9 with SMTP id af79cd13be357-914b50ca4femr357532085a.16.1779449614900; Fri, 22 May 2026 04:33:34 -0700 (PDT) MIME-Version: 1.0 References: <978D8971-08C3-4AAD-AE8B-976D753C882A@gmail.com> <6B9A85F9-B632-4286-98AF-9EC435019055@gmail.com> In-Reply-To: <6B9A85F9-B632-4286-98AF-9EC435019055@gmail.com> From: Rafia Sabih Date: Fri, 22 May 2026 13:33:21 +0200 X-Gm-Features: AVHnY4JmLtCUhpJEQSYUnEQJ-GyoXVTtatt1txskvx3cucrTqv_RhKMByRGoXLo Message-ID: Subject: Re: Set notice receiver before libpq connection startup To: Chao Li Cc: vignesh C , Fujii Masao , PostgreSQL-development Content-Type: multipart/alternative; boundary="0000000000003121870652666645" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --0000000000003121870652666645 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Thu, 21 May 2026 at 09:27, Chao Li wrote: > > > > On May 21, 2026, at 13:03, vignesh C wrote: > > > > On Thu, 21 May 2026 at 07:40, Chao Li wrote: > >> > >> > >> > >>> On May 20, 2026, at 17:19, Fujii Masao wrote: > >>> > >>> On Wed, May 20, 2026 at 4:21=E2=80=AFPM Chao Li > wrote: > >>>> > >>>> Hi, > >>>> > >>>> While testing =E2=80=9CLog remote NOTICE, WARNING, and similar messa= ges using > ereport()=E2=80=9D, I noticed that libpqsrv_notice_receiver is only insta= lled after > libpqsrv_connect() finishes. As a result, NOTICE messages generated durin= g > connection establishment are missed by ereport() and are still printed to > stderr. > >>>> > >>>> To reproduce the issue, I created a separate database called remoted= b > 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=3D# create extension dblink; > >>>> CREATE EXTENSION > >>>> evantest=3D# SELECT dblink_connect('host=3D127.0.0.1 port=3D5432 > dbname=3Dremotedb user=3Dchaol sslmode=3Ddisable gssencmode=3Ddisable'); > >>>> 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=3D127.0.0.1 port=3D5432 dbname=3Dremotedb user=3Dcha= ol > sslmode=3Ddisable gssencmode=3Ddisable'); > >>>> 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 remot= e > connection: NOTICE: startup notice from remotedb login trigger > >>>> 2026-05-20 14:44:49.296 CST [45567] STATEMENT: SELECT > dblink_connect('host=3D127.0.0.1 port=3D5432 dbname=3Dremotedb user=3Dcha= ol > sslmode=3Ddisable gssencmode=3Ddisable'); > >>>> ``` > >>>> > >>>> Please see the attached patch for details. > >>> > >>> Thanks for the report and patch! > >>> > >>> I'd prefer to avoid adding notice-receiver-specific wrappers such as > >>> libpqsrv_connect_with_notice_receiver(). Instead, how about splitting > >>> libpqsrv_connect() into two steps: libpqsrv_connect_start(), which > performs > >>> libpqsrv_connect_prepare() and PQconnectStart(), and > >>> libpqsrv_connect_complete(), which runs libpqsrv_connect_internal()? > >>> > >>> With this approach, callers could invoke PQsetNoticeReceiver() after > >>> libpqsrv_connect_start() returns but before > libpqsrv_connect_complete() is > >>> called. This would allow startup-time notices to be handled correctly > without > >>> introducing a dedicated wrapper function. > >>> > >>> Compared to the *_with_notice_receiver() approach, this design is mor= e > >>> general because it exposes the phase between PQconnectStart() and > connection > >>> completion. It could also support other kinds of per-connection setup > in the > >>> future, not just notice receiver installation. Thought? > >>> > >>> Regards, > >>> > >>> -- > >>> Fujii Masao > >> > >> The idea sounds good to me, so v2 is implemented following that idea. > >> > >> A few things I want to point out abut v2: > >> > >> * Since libpqsrv_connect_complete() would only wrap > libpqsrv_connect_internal(), I just renamed libpqsrv_connect_internal() t= o > libpqsrv_connect_complete(). > >> * Since libpqsrv_connect() is now split into two phases, > libpqsrv_connect_complete() must be called even if conn is NULL, because = it > may need to call ReleaseExternalFD(). I mentioned this in the header > comment of libpqsrv_connect_start(). > >> * In the postgres_fdw/connection.c change, I introduced a new local > variable, start_conn, to keep the original logic unchanged. Because there > is a PG_TRY/PG_CATCH block, conn is assigned only after > libpqsrv_connect_complete() finishes successfully. > > > > Thanks for reporting this issue. I was able to reproduce the issue > > with the steps provided and your patch fixes the issue. > > Few comments: > > 1) No need of conn variable here, we can directly return > > PQconnectStart(conninfo) in this function: > > +static inline PGconn * > > +libpqsrv_connect_start(const char *conninfo) > > +{ > > + PGconn *conn =3D NULL; > > + > > + libpqsrv_connect_prepare(); > > + > > + conn =3D PQconnectStart(conninfo); > > + > > + return conn; > > +} > > > > 2) Similarly here too: > > +static inline PGconn * > > +libpqsrv_connect_params_start(const char *const *keywords, > > + const char *const *values, > > + int expand_dbname) > > { > > PGconn *conn =3D NULL; > > > > libpqsrv_connect_prepare(); > > > > - conn =3D PQconnectStart(conninfo); > > - > > - libpqsrv_connect_internal(conn, wait_event_info); > > + conn =3D PQconnectStartParams(keywords, values, expand_dbname); > > > > return conn; > > } > > > > Regards, > > Vignesh > > Thanks for your comment. Addressed in v3. > > Here are my two cents, we need not to check conn is null here + conn =3D libpqsrv_connect_start(connstr); + if (conn !=3D NULL) + PQsetNoticeReceiver(conn, libpqsrv_notice_receiver, + "received message via remote connection"); because it is done so in PQsetNoticeReceiver anyway. Also, since there is no else here so it doesn't make sense more, because if it is null then also we will just continue with the next function call. Another point is, in pg_connect_server I don't get the value of adding another PGConn variable start_conn, can't we use conn itself...? I hope this helps. --=20 Regards, Rafia Sabih CYBERTEC PostgreSQL International GmbH --0000000000003121870652666645 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable


On Thu, 21 May = 2026 at 09:27, Chao Li <li.eva= n.chao@gmail.com> wrote:


> On May 21, 2026, at 13:03, vignesh C <vignesh21@gmail.com> wrote:
>
> On Thu, 21 May 2026 at 07:40, Chao Li <li.evan.chao@gmail.com> wrote:
>>
>>
>>
>>> On May 20, 2026, at 17:19, Fujii Masao <masao.fujii@gmail.com> wrote= :
>>>
>>> On Wed, May 20, 2026 at 4:21=E2=80=AFPM Chao Li <li.evan.chao@gmail.com> wrote:
>>>>
>>>> Hi,
>>>>
>>>> While testing =E2=80=9CLog remote NOTICE, WARNING, and sim= ilar messages using ereport()=E2=80=9D, I noticed that libpqsrv_notice_rece= iver is only installed after libpqsrv_connect() finishes. As a result, NOTI= CE messages generated during connection establishment are missed by ereport= () and are still printed to stderr.
>>>>
>>>> To reproduce the issue, I created a separate database call= ed 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 trigg= er';
>>>> END;
>>>> $$;
>>>>
>>>> CREATE EVENT TRIGGER repro_login_notice_trg
>>>> ON login
>>>> EXECUTE FUNCTION repro_login_notice();
>>>>
>>>> ALTER EVENT TRIGGER repro_login_notice_trg ENABLE ALWAYS;<= br> >>>> ```
>>>>
>>>> Then, from another database:
>>>> ```
>>>> evantest=3D# create extension dblink;
>>>> CREATE EXTENSION
>>>> evantest=3D# SELECT dblink_connect('host=3D127.0.0.1 p= ort=3D5432 dbname=3Dremotedb user=3Dchaol sslmode=3Ddisable gssencmode=3Ddi= sable');
>>>> 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:=C2=A0 SELEC= T dblink_connect('host=3D127.0.0.1 port=3D5432 dbname=3Dremotedb user= =3Dchaol sslmode=3Ddisable gssencmode=3Ddisable');
>>>> NOTICE:=C2=A0 startup notice from remotedb login trigger >>>> ```
>>>>
>>>> To fix that, I think we should install libpqsrv_notice_rec= eiver before libpqsrv_connect_internal(). In the attached patch, I added tw= o helpers: libpqsrv_connect_with_notice_receiver() and libpqsrv_connect_par= ams_with_notice_receiver().
>>>>
>>>> With the fix, the NOTICE message now looks like this:
>>>> ```
>>>> 2026-05-20 14:44:49.296 CST [45567] LOG:=C2=A0 received me= ssage via remote connection: NOTICE:=C2=A0 startup notice from remotedb log= in trigger
>>>> 2026-05-20 14:44:49.296 CST [45567] STATEMENT:=C2=A0 SELEC= T dblink_connect('host=3D127.0.0.1 port=3D5432 dbname=3Dremotedb user= =3Dchaol sslmode=3Ddisable gssencmode=3Ddisable');
>>>> ```
>>>>
>>>> Please see the attached patch for details.
>>>
>>> Thanks for the report and patch!
>>>
>>> I'd prefer to avoid adding notice-receiver-specific wrappe= rs such as
>>> libpqsrv_connect_with_notice_receiver(). Instead, how about sp= litting
>>> libpqsrv_connect() into two steps: libpqsrv_connect_start(), w= hich performs
>>> libpqsrv_connect_prepare() and PQconnectStart(), and
>>> libpqsrv_connect_complete(), which runs libpqsrv_connect_inter= nal()?
>>>
>>> With this approach, callers could invoke PQsetNoticeReceiver()= after
>>> libpqsrv_connect_start() returns but before libpqsrv_connect_c= omplete() is
>>> called. This would allow startup-time notices to be handled co= rrectly without
>>> introducing a dedicated wrapper function.
>>>
>>> Compared to the *_with_notice_receiver() approach, this design= is more
>>> general because it exposes the phase between PQconnectStart() = and connection
>>> completion. It could also support other kinds of per-connectio= n setup in the
>>> future, not just notice receiver installation. Thought?
>>>
>>> Regards,
>>>
>>> --
>>> Fujii Masao
>>
>> The idea sounds good to me, so v2 is implemented following that id= ea.
>>
>> A few things I want to point out abut v2:
>>
>> * Since libpqsrv_connect_complete() would only wrap libpqsrv_conne= ct_internal(), I just renamed libpqsrv_connect_internal() to libpqsrv_conne= ct_complete().
>> * Since libpqsrv_connect() is now split into two phases, libpqsrv_= connect_complete() must be called even if conn is NULL, because it may need= to call ReleaseExternalFD(). I mentioned this in the header comment of lib= pqsrv_connect_start().
>> * In the postgres_fdw/connection.c change, I introduced a new loca= l variable, start_conn, to keep the original logic unchanged. Because there= is a PG_TRY/PG_CATCH block, conn is assigned only after libpqsrv_connect_c= omplete() finishes successfully.
>
> Thanks for reporting this issue. I was able to reproduce the issue
> with the steps provided and your patch fixes the issue.
> Few comments:
> 1) No need of conn variable here, we can directly return
> PQconnectStart(conninfo) in this function:
> +static inline PGconn *
> +libpqsrv_connect_start(const char *conninfo)
> +{
> + PGconn=C2=A0 =C2=A0 *conn =3D NULL;
> +
> + libpqsrv_connect_prepare();
> +
> + conn =3D PQconnectStart(conninfo);
> +
> + return conn;
> +}
>
> 2) Similarly here too:
> +static inline PGconn *
> +libpqsrv_connect_params_start(const char *const *keywords,
> +=C2=A0 =C2=A0const char *const *values,
> +=C2=A0 =C2=A0int expand_dbname)
> {
>=C2=A0 PGconn=C2=A0 =C2=A0 *conn =3D NULL;
>
>=C2=A0 libpqsrv_connect_prepare();
>
> - conn =3D PQconnectStart(conninfo);
> -
> - libpqsrv_connect_internal(conn, wait_event_info);
> + conn =3D PQconnectStartParams(keywords, values, expand_dbname);
>
>=C2=A0 return conn;
> }
>
> Regards,
> Vignesh

Thanks for your comment. Addressed in v3.

= + conn =3D libpqsrv_connect_start(connstr);
+ if (conn !=3D NULL)
+= PQsetNoticeReceiver(conn, libpqsrv_notice_receiver,
+ &qu= ot;received message via remote connection");
because it is d= one so in=C2=A0 PQsetNoticeReceiver anyway. Also, since there is no else he= re so it doesn't make sense more, because if it is null then also we wi= ll just continue with the next function call.

Another point is, in pg_connect_server I don't get the value of addin= g another PGConn variable start_conn, can't we use conn itself...?
I hope this helps.
--
Regards= ,
Rafia Sabih
CYBERTEC PostgreSQL International GmbH
=
--0000000000003121870652666645--