aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPeter Eisentraut <peter_e@gmx.net>2017-06-03 09:18:52 -0400
committerPeter Eisentraut <peter_e@gmx.net>2017-06-03 09:20:56 -0400
commit3c9bc2157a4f465b3c070d1250597568d2dc285f (patch)
treeb2d5d9831852365bb6e2a08141ffdbb8665ecf71 /src
parent34aebcf42a70089b76ff8e9ccda331f111153eeb (diff)
downloadpostgresql-3c9bc2157a4f465b3c070d1250597568d2dc285f.tar.gz
postgresql-3c9bc2157a4f465b3c070d1250597568d2dc285f.zip
Make tablesync worker exit when apply dies while it was waiting for it
This avoids "orphaned" sync workers. This was caused by a thinko in wait_for_sync_status_change. Author: Petr Jelinek <petr.jelinek@2ndquadrant.com> Reported-by: Masahiko Sawada <sawada.mshk@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/backend/replication/logical/tablesync.c24
1 files changed, 21 insertions, 3 deletions
diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c
index 85e480db4bd..6e268f3521d 100644
--- a/src/backend/replication/logical/tablesync.c
+++ b/src/backend/replication/logical/tablesync.c
@@ -146,7 +146,12 @@ finish_sync_worker(void)
/*
* Wait until the table synchronization change.
*
- * Returns false if the relation subscription state disappeared.
+ * If called from apply worker, it will wait for the synchronization worker to
+ * change table state in shmem. If called from synchronization worker, it
+ * will wait for apply worker to change table state in shmem.
+ *
+ * Returns false if the opposite worker has disappeared or the table state has
+ * been reset.
*/
static bool
wait_for_sync_status_change(Oid relid, char origstate)
@@ -161,14 +166,27 @@ wait_for_sync_status_change(Oid relid, char origstate)
CHECK_FOR_INTERRUPTS();
LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
+
+ /* Check if the opposite worker is still running and bail if not. */
worker = logicalrep_worker_find(MyLogicalRepWorker->subid,
- relid, false);
+ am_tablesync_worker() ? InvalidOid : relid,
+ false);
if (!worker)
{
LWLockRelease(LogicalRepWorkerLock);
return false;
}
+
+ /*
+ * If I'm the synchronization worker, look at my own state. Otherwise
+ * look at the state of the synchronization worker we found above.
+ */
+ if (am_tablesync_worker())
+ worker = MyLogicalRepWorker;
+
+ Assert(worker->relid == relid);
state = worker->relstate;
+
LWLockRelease(LogicalRepWorkerLock);
if (state == SUBREL_STATE_UNKNOWN)
@@ -179,7 +197,7 @@ wait_for_sync_status_change(Oid relid, char origstate)
rc = WaitLatch(&MyProc->procLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- 10000L, WAIT_EVENT_LOGICAL_SYNC_STATE_CHANGE);
+ 1000L, WAIT_EVENT_LOGICAL_SYNC_STATE_CHANGE);
/* emergency bailout if postmaster has died */
if (rc & WL_POSTMASTER_DEATH)