Skip to content

Commit 2e37286

Browse files
committed
Don't let libpq PGEVT_CONNRESET callbacks break a PGconn.
As currently implemented, failure of a PGEVT_CONNRESET callback forces the PGconn into the CONNECTION_BAD state (without closing the socket, which is inconsistent with other failure paths), and prevents later callbacks from being called. This seems highly questionable, and indeed is questioned by comments in the source. Instead, let's just ignore the result value of PGEVT_CONNRESET calls. Like the preceding commit, this converts event callbacks into "pure observers" that cannot affect libpq's processing logic. Discussion: https://postgr.es/m/3185105.1644960083@sss.pgh.pa.us
1 parent ce1e7a2 commit 2e37286

File tree

2 files changed

+11
-28
lines changed

2 files changed

+11
-28
lines changed

doc/src/sgml/libpq.sgml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7183,12 +7183,11 @@ typedef struct
71837183
<para>
71847184
The connection reset event is fired on completion of
71857185
<xref linkend="libpq-PQreset"/> or <function>PQresetPoll</function>. In
7186-
both cases, the event is only fired if the reset was successful. If
7187-
the event procedure fails, the entire connection reset will fail; the
7188-
<structname>PGconn</structname> is put into
7189-
<literal>CONNECTION_BAD</literal> status and
7190-
<function>PQresetPoll</function> will return
7191-
<literal>PGRES_POLLING_FAILED</literal>.
7186+
both cases, the event is only fired if the reset was successful.
7187+
The return value of the event procedure is ignored
7188+
in <productname>PostgreSQL</productname> v15 and later.
7189+
With earlier versions, however, it's important to return success
7190+
(nonzero) or the connection will be aborted.
71927191

71937192
<synopsis>
71947193
typedef struct

src/interfaces/libpq/fe-connect.c

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4276,8 +4276,7 @@ PQreset(PGconn *conn)
42764276
if (connectDBStart(conn) && connectDBComplete(conn))
42774277
{
42784278
/*
4279-
* Notify event procs of successful reset. We treat an event proc
4280-
* failure as disabling the connection ... good idea?
4279+
* Notify event procs of successful reset.
42814280
*/
42824281
int i;
42834282

@@ -4286,15 +4285,8 @@ PQreset(PGconn *conn)
42864285
PGEventConnReset evt;
42874286

42884287
evt.conn = conn;
4289-
if (!conn->events[i].proc(PGEVT_CONNRESET, &evt,
4290-
conn->events[i].passThrough))
4291-
{
4292-
conn->status = CONNECTION_BAD;
4293-
appendPQExpBuffer(&conn->errorMessage,
4294-
libpq_gettext("PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n"),
4295-
conn->events[i].name);
4296-
break;
4297-
}
4288+
(void) conn->events[i].proc(PGEVT_CONNRESET, &evt,
4289+
conn->events[i].passThrough);
42984290
}
42994291
}
43004292
}
@@ -4336,8 +4328,7 @@ PQresetPoll(PGconn *conn)
43364328
if (status == PGRES_POLLING_OK)
43374329
{
43384330
/*
4339-
* Notify event procs of successful reset. We treat an event proc
4340-
* failure as disabling the connection ... good idea?
4331+
* Notify event procs of successful reset.
43414332
*/
43424333
int i;
43434334

@@ -4346,15 +4337,8 @@ PQresetPoll(PGconn *conn)
43464337
PGEventConnReset evt;
43474338

43484339
evt.conn = conn;
4349-
if (!conn->events[i].proc(PGEVT_CONNRESET, &evt,
4350-
conn->events[i].passThrough))
4351-
{
4352-
conn->status = CONNECTION_BAD;
4353-
appendPQExpBuffer(&conn->errorMessage,
4354-
libpq_gettext("PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n"),
4355-
conn->events[i].name);
4356-
return PGRES_POLLING_FAILED;
4357-
}
4340+
(void) conn->events[i].proc(PGEVT_CONNRESET, &evt,
4341+
conn->events[i].passThrough);
43584342
}
43594343
}
43604344

0 commit comments

Comments
 (0)