Skip to content

Commit ecc59e3

Browse files
committed
Client-side fixes for delayed NOTIFY receipt.
PQnotifies() is defined to just process already-read data, not try to read any more from the socket. (This is a debatable decision, perhaps, but I'm hesitant to change longstanding library behavior.) The documentation has long recommended calling PQconsumeInput() before PQnotifies() to ensure that any already-arrived message would get absorbed and processed. However, psql did not get that memo, which explains why it's not very reliable about reporting notifications promptly. Also, most (not quite all) callers called PQconsumeInput() just once before a PQnotifies() loop. Taking this recommendation seriously implies that we should do PQconsumeInput() before each call. This is more important now that we have "payload" strings in notification messages than it was before; that increases the probability of having more than one packet's worth of notify messages. Hence, adjust code as well as documentation examples to do it like that. Back-patch to 9.5 to match related server fixes. In principle we could probably go back further with these changes, but given lack of field complaints I doubt it's worthwhile. Discussion: https://postgr.es/m/CAOYf6ec-TmRYjKBXLLaGaB-jrd=mjG1Hzn1a1wufUAR39PQYhw@mail.gmail.com
1 parent 3bdef6d commit ecc59e3

File tree

5 files changed

+12
-4
lines changed

5 files changed

+12
-4
lines changed

doc/src/sgml/libpq.sgml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5215,7 +5215,7 @@ typedef struct pgNotify
52155215
<para>
52165216
<function>PQnotifies</function> does not actually read data from the
52175217
server; it just returns messages previously absorbed by another
5218-
<application>libpq</application> function. In prior releases of
5218+
<application>libpq</application> function. In ancient releases of
52195219
<application>libpq</application>, the only way to ensure timely receipt
52205220
of <command>NOTIFY</> messages was to constantly submit commands, even
52215221
empty ones, and then check <function>PQnotifies</function> after each
@@ -8608,6 +8608,7 @@ main(int argc, char **argv)
86088608
notify->relname, notify->be_pid);
86098609
PQfreemem(notify);
86108610
nnotifies++;
8611+
PQconsumeInput(conn);
86118612
}
86128613
}
86138614

src/bin/psql/common.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -788,7 +788,8 @@ PrintNotifications(void)
788788
{
789789
PGnotify *notify;
790790

791-
while ((notify = PQnotifies(pset.db)))
791+
PQconsumeInput(pset.db);
792+
while ((notify = PQnotifies(pset.db)) != NULL)
792793
{
793794
/* for backward compatibility, only show payload if nonempty */
794795
if (notify->extra[0])
@@ -799,6 +800,7 @@ PrintNotifications(void)
799800
notify->relname, notify->be_pid);
800801
fflush(pset.queryFout);
801802
PQfreemem(notify);
803+
PQconsumeInput(pset.db);
802804
}
803805
}
804806

src/interfaces/ecpg/ecpglib/execute.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1729,12 +1729,13 @@ ecpg_process_output(struct statement *stmt, bool clear_result)
17291729
}
17301730

17311731
/* check for asynchronous returns */
1732-
notify = PQnotifies(stmt->connection->connection);
1733-
if (notify)
1732+
PQconsumeInput(stmt->connection->connection);
1733+
while ((notify = PQnotifies(stmt->connection->connection)) != NULL)
17341734
{
17351735
ecpg_log("ecpg_process_output on line %d: asynchronous notification of \"%s\" from backend PID %d received\n",
17361736
stmt->lineno, notify->relname, notify->be_pid);
17371737
PQfreemem(notify);
1738+
PQconsumeInput(stmt->connection->connection);
17381739
}
17391740

17401741
return status;

src/interfaces/libpq/fe-exec.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2239,6 +2239,9 @@ PQsendDescribe(PGconn *conn, char desc_type, const char *desc_target)
22392239
* no unhandled async notification from the backend
22402240
*
22412241
* the CALLER is responsible for FREE'ing the structure returned
2242+
*
2243+
* Note that this function does not read any new data from the socket;
2244+
* so usually, caller should call PQconsumeInput() first.
22422245
*/
22432246
PGnotify *
22442247
PQnotifies(PGconn *conn)

src/test/examples/testlibpq2.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ main(int argc, char **argv)
140140
notify->relname, notify->be_pid);
141141
PQfreemem(notify);
142142
nnotifies++;
143+
PQconsumeInput(conn);
143144
}
144145
}
145146

0 commit comments

Comments
 (0)