0001-signal-backends-on-commit.patch
text/x-patch
Filename: 0001-signal-backends-on-commit.patch
Type: text/x-patch
Part: 0
Patch
Format: unified
Series: patch 0001
| File | + | − |
|---|---|---|
| src/backend/commands/async.c | 29 | 21 |
diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c
index 4b16fb5682..9093af42bd 100644
--- a/src/backend/commands/async.c
+++ b/src/backend/commands/async.c
@@ -69,16 +69,18 @@
*
* After commit we are called another time (AtCommit_Notify()). Here we
* make the actual updates to the effective listen state (listenChannels).
+ * Also we check if we need to signal listening backends. In
+ * SignalBackends() we scan the list of listening backends and send a
+ * PROCSIG_NOTIFY_INTERRUPT signal to every listening backend (we don't know
+ * which backend is listening on which channel so we must signal them all).
+ * We can exclude backends that are already up to date, though, and we can
+ * also exclude backends that are in other databases (unless they are way
+ * behind and should be kicked to make them advance their pointers).
+ * We don't bother with a self-signal either.
*
* Finally, after we are out of the transaction altogether, we check if
- * we need to signal listening backends. In SignalBackends() we scan the
- * list of listening backends and send a PROCSIG_NOTIFY_INTERRUPT signal
- * to every listening backend (we don't know which backend is listening on
- * which channel so we must signal them all). We can exclude backends that
- * are already up to date, though, and we can also exclude backends that
- * are in other databases (unless they are way behind and should be kicked
- * to make them advance their pointers). We don't bother with a
- * self-signal either, but just process the queue directly.
+ * we need to send out self-notifies. In ProcessCompletedNotifies() we just
+ * process the queue directly.
*
* 5. Upon receipt of a PROCSIG_NOTIFY_INTERRUPT signal, the signal handler
* sets the process's latch, which triggers the event to be processed
@@ -984,7 +986,9 @@ PreCommit_Notify(void)
*
* This is called at transaction commit, after committing to clog.
*
- * Update listenChannels and clear transaction-local state.
+ * Update listenChannels and clear transaction-local state. If we issued
+ * any notifications in the transaction, send signals to other backends to
+ * process them.
*/
void
AtCommit_Notify(void)
@@ -1027,6 +1031,13 @@ AtCommit_Notify(void)
if (amRegisteredListener && listenChannels == NIL)
asyncQueueUnregister();
+ /*
+ * Send signals to other backends. We call SignalBackends() only if there
+ * are pending notifies which are added to the queue by PreCommit_Notify().
+ */
+ if (pendingNotifies != NULL)
+ SignalBackends();
+
/* And clean up */
ClearPendingActionsAndNotifies();
}
@@ -1200,14 +1211,13 @@ Exec_UnlistenAllCommit(void)
}
/*
- * ProcessCompletedNotifies --- send out signals and self-notifies
+ * ProcessCompletedNotifies --- send out self-notifies
*
* This is called from postgres.c just before going idle at the completion
* of a transaction. If we issued any notifications in the just-completed
- * transaction, send signals to other backends to process them, and also
- * process the queue ourselves to send messages to our own frontend.
- * Also, if we filled enough queue pages with new notifies, try to advance
- * the queue tail pointer.
+ * transaction, process the queue ourselves to send messages to our own
+ * frontend. Also, if we filled enough queue pages with new notifies, try to
+ * advance the queue tail pointer.
*
* The reason that this is not done in AtCommit_Notify is that there is
* a nonzero chance of errors here (for example, encoding conversion errors
@@ -1216,9 +1226,8 @@ Exec_UnlistenAllCommit(void)
* to ensure that a transaction's self-notifies are delivered to the frontend
* before it gets the terminating ReadyForQuery message.
*
- * Note that we send signals and process the queue even if the transaction
- * eventually aborted. This is because we need to clean out whatever got
- * added to the queue.
+ * Note that we process the queue even if the transaction eventually aborted.
+ * This is because we need to clean out whatever got added to the queue.
*
* NOTE: we are outside of any transaction here.
*/
@@ -1253,9 +1262,6 @@ ProcessCompletedNotifies(void)
*/
StartTransactionCommand();
- /* Send signals to other backends */
- SignalBackends();
-
if (listenChannels != NIL)
{
/* Read the queue ourselves, and send relevant stuff to the frontend */
@@ -1658,7 +1664,8 @@ asyncQueueFillWarning(void)
/*
* Send signals to listening backends.
*
- * We never signal our own process; that should be handled by our caller.
+ * We never signal our own process; that should be handled by
+ * ProcessCompletedNotifies().
*
* Normally we signal only backends in our own database, since only those
* backends could be interested in notifies we send. However, if there's
@@ -2268,6 +2275,7 @@ ProcessIncomingNotify(void)
/* We *must* reset the flag */
notifyInterruptPending = false;
+
/* Do nothing else if we aren't actively listening */
if (listenChannels == NIL)
return;