*** a/src/backend/replication/logical/launcher.c
--- b/src/backend/replication/logical/launcher.c
***************
*** 42,47 ****
--- 42,48 ----
  #include "replication/worker_internal.h"
  
  #include "storage/ipc.h"
+ #include "storage/lmgr.h"
  #include "storage/proc.h"
  #include "storage/procarray.h"
  #include "storage/procsignal.h"
***************
*** 116,122 **** get_subscription_list(void)
  	StartTransactionCommand();
  	(void) GetTransactionSnapshot();
  
! 	rel = heap_open(SubscriptionRelationId, AccessShareLock);
  	scan = heap_beginscan_catalog(rel, 0, NULL);
  
  	while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection)))
--- 117,131 ----
  	StartTransactionCommand();
  	(void) GetTransactionSnapshot();
  
! 	/*
! 	 * This lock cannot be aquired while subsciption commands are updating the
! 	 * relation. We can safely skip over for the case.
! 	 */
! 	if (!ConditionalLockRelationOid(SubscriptionRelationId, AccessShareLock))
! 		return NIL;
! 
! 	rel = heap_open(SubscriptionRelationId, NoLock);
! 
  	scan = heap_beginscan_catalog(rel, 0, NULL);
  
  	while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection)))
***************
*** 146,152 **** get_subscription_list(void)
  	}
  
  	heap_endscan(scan);
! 	heap_close(rel, AccessShareLock);
  
  	CommitTransactionCommand();
  
--- 155,162 ----
  	}
  
  	heap_endscan(scan);
! 	heap_close(rel, NoLock);
! 	UnlockRelationOid(SubscriptionRelationId, AccessShareLock);
  
  	CommitTransactionCommand();
  
***************
*** 403,410 **** retry:
  }
  
  /*
   * Stop the logical replication worker and wait until it detaches from the
!  * slot.
   */
  void
  logicalrep_worker_stop(Oid subid, Oid relid)
--- 413,465 ----
  }
  
  /*
+  * Stop all table sync workers associated with given subid.
+  *
+  * This function is called by apply worker. Since table sync
+  * worker associated with same subscription is launched by
+  * only the apply worker. We don't need to acquire
+  * LogicalRepLauncherLock here.
+  */
+ void
+ logicalrep_sync_workers_stop(Oid subid)
+ {
+ 	List *relid_list = NIL;
+ 	ListCell *cell;
+ 	int	i;
+ 
+ 	LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
+ 
+ 	/*
+ 	 * Walks the workers array and get relid list that matches
+ 	 * given subscription id.
+ 	 */
+ 	for (i = 0; i < max_logical_replication_workers; i++)
+ 	{
+ 		LogicalRepWorker *w = &LogicalRepCtx->workers[i];
+ 
+ 		if (w->in_use && w->subid == subid &&
+ 			OidIsValid(w->relid))
+ 			relid_list = lappend_oid(relid_list, w->relid);
+ 	}
+ 
+ 	LWLockRelease(LogicalRepWorkerLock);
+ 
+ 	/* Return if there is no table sync worker associated with myself */
+ 	if (relid_list == NIL)
+ 		return;
+ 
+ 	foreach (cell, relid_list)
+ 	{
+ 		Oid	relid = lfirst_oid(cell);
+ 
+ 		logicalrep_worker_stop(subid, relid);
+ 	}
+ }
+ 
+ /*
   * Stop the logical replication worker and wait until it detaches from the
!  * slot. This function can be called by both logical replication launcher
!  * and apply worker to stop apply worker and table sync worker.
   */
  void
  logicalrep_worker_stop(Oid subid, Oid relid)
***************
*** 570,575 **** logicalrep_worker_attach(int slot)
--- 625,634 ----
  static void
  logicalrep_worker_detach(void)
  {
+ 	/* Stop all sync workers associated if apply worker */
+ 	if (!am_tablesync_worker())
+ 		logicalrep_sync_workers_stop(MyLogicalRepWorker->subid);
+ 
  	/* Block concurrent access. */
  	LWLockAcquire(LogicalRepWorkerLock, LW_EXCLUSIVE);
  
*** a/src/backend/replication/logical/worker.c
--- b/src/backend/replication/logical/worker.c
***************
*** 1455,1468 **** ApplyWorkerMain(Datum main_arg)
  	char		   *myslotname;
  	WalRcvStreamOptions options;
  
- 	/* Attach to slot */
- 	logicalrep_worker_attach(worker_slot);
- 
  	/* Setup signal handling */
  	pqsignal(SIGHUP, logicalrep_worker_sighup);
  	pqsignal(SIGTERM, logicalrep_worker_sigterm);
  	BackgroundWorkerUnblockSignals();
  
  	/* Initialise stats to a sanish value */
  	MyLogicalRepWorker->last_send_time = MyLogicalRepWorker->last_recv_time =
  		MyLogicalRepWorker->reply_time = GetCurrentTimestamp();
--- 1455,1471 ----
  	char		   *myslotname;
  	WalRcvStreamOptions options;
  
  	/* Setup signal handling */
  	pqsignal(SIGHUP, logicalrep_worker_sighup);
  	pqsignal(SIGTERM, logicalrep_worker_sigterm);
  	BackgroundWorkerUnblockSignals();
  
+ 	/*
+ 	 * Attach to slot. This should be after signal handling setup since
+ 	 * signals may come as soon as attached.
+ 	 */
+ 	logicalrep_worker_attach(worker_slot);
+ 
  	/* Initialise stats to a sanish value */
  	MyLogicalRepWorker->last_send_time = MyLogicalRepWorker->last_recv_time =
  		MyLogicalRepWorker->reply_time = GetCurrentTimestamp();
***************
*** 1492,1498 **** ApplyWorkerMain(Datum main_arg)
  											  ALLOCSET_DEFAULT_SIZES);
  	StartTransactionCommand();
  	oldctx = MemoryContextSwitchTo(ApplyContext);
! 	MySubscription = GetSubscription(MyLogicalRepWorker->subid, false);
  	MySubscriptionValid = true;
  	MemoryContextSwitchTo(oldctx);
  
--- 1495,1532 ----
  											  ALLOCSET_DEFAULT_SIZES);
  	StartTransactionCommand();
  	oldctx = MemoryContextSwitchTo(ApplyContext);
! 
! 	/*
! 	 * Wait for the catalog is available. The subscription for this worker
! 	 * might be already dropped.  We should receive SIGTERM in the case so
! 	 * obey it.
! 	 */
! 	while (!ConditionalLockRelationOid(SubscriptionRelationId, AccessShareLock))
! 	{
! 		pg_usleep(500 * 1000L); /* 0.5s */
! 
! 		/* We are apparently killed, exit silently. */
! 		if (got_SIGTERM)
! 			proc_exit(0);
! 	}
! 
! 	MySubscription = GetSubscription(MyLogicalRepWorker->subid, true);
! 	UnlockRelationOid(SubscriptionRelationId, AccessShareLock);
! 
! 	/* There's a race codition here. Check if MySubscription is valid. */
! 	if (MySubscription == NULL)
! 	{
! 		/* If we got SIGTERM, we are explicitly killed */
! 		if (got_SIGTERM)
! 			proc_exit(0);
! 
! 		/* Otherwise something uncertain happned */
! 		ereport(ERROR,
! 				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
! 				 errmsg("subscription for this worker not found: %s",
! 						MySubscription->name)));
! 	}
! 
  	MySubscriptionValid = true;
  	MemoryContextSwitchTo(oldctx);
  
*** a/src/include/replication/worker_internal.h
--- b/src/include/replication/worker_internal.h
***************
*** 78,83 **** extern void logicalrep_worker_launch(Oid dbid, Oid subid, const char *subname,
--- 78,84 ----
  extern void logicalrep_worker_stop(Oid subid, Oid relid);
  extern void logicalrep_worker_wakeup(Oid subid, Oid relid);
  extern void logicalrep_worker_wakeup_ptr(LogicalRepWorker *worker);
+ extern void logicalrep_sync_workers_stop(Oid subid);
  
  extern int logicalrep_sync_worker_count(Oid subid);
  
