diff --git a/src/backend/postmaster/startup.c b/src/backend/postmaster/startup.c
new file mode 100644
index 581837a..b993ca8
*** a/src/backend/postmaster/startup.c
--- b/src/backend/postmaster/startup.c
*************** StartupProcessMain(void)
*** 203,208 ****
--- 203,209 ----
  	 */
  	RegisterTimeout(STANDBY_DEADLOCK_TIMEOUT, StandbyDeadLockHandler);
  	RegisterTimeout(STANDBY_TIMEOUT, StandbyTimeoutHandler);
+ 	RegisterTimeout(STANDBY_LOCK_TIMEOUT, StandbyLockTimeoutHandler);
  
  	/*
  	 * Unblock signals (they were blocked when the postmaster forked us)
diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c
new file mode 100644
index 292bed5..4b428de
*** a/src/backend/storage/ipc/standby.c
--- b/src/backend/storage/ipc/standby.c
*************** static List *RecoveryLockList;
*** 41,47 ****
  
  static void ResolveRecoveryConflictWithVirtualXIDs(VirtualTransactionId *waitlist,
  									   ProcSignalReason reason);
- static void ResolveRecoveryConflictWithLock(Oid dbOid, Oid relOid);
  static void SendRecoveryConflictWithBufferPin(ProcSignalReason reason);
  static XLogRecPtr LogCurrentRunningXacts(RunningTransactions CurrRunningXacts);
  static void LogAccessExclusiveLocks(int nlocks, xl_standby_lock *locks);
--- 41,46 ----
*************** ResolveRecoveryConflictWithDatabase(Oid
*** 337,375 ****
  	}
  }
  
! static void
! ResolveRecoveryConflictWithLock(Oid dbOid, Oid relOid)
  {
! 	VirtualTransactionId *backends;
! 	bool		lock_acquired = false;
! 	int			num_attempts = 0;
! 	LOCKTAG		locktag;
  
! 	SET_LOCKTAG_RELATION(locktag, dbOid, relOid);
  
! 	/*
! 	 * If blowing away everybody with conflicting locks doesn't work, after
! 	 * the first two attempts then we just start blowing everybody away until
! 	 * it does work. We do this because its likely that we either have too
! 	 * many locks and we just can't get one at all, or that there are many
! 	 * people crowding for the same table. Recovery must win; the end
! 	 * justifies the means.
! 	 */
! 	while (!lock_acquired)
! 	{
! 		if (++num_attempts < 3)
! 			backends = GetLockConflicts(&locktag, AccessExclusiveLock);
! 		else
! 			backends = GetConflictingVirtualXIDs(InvalidTransactionId,
! 												 InvalidOid);
  
  		ResolveRecoveryConflictWithVirtualXIDs(backends,
  											 PROCSIG_RECOVERY_CONFLICT_LOCK);
  
! 		if (LockAcquireExtended(&locktag, AccessExclusiveLock, true, true, false)
! 			!= LOCKACQUIRE_NOT_AVAIL)
! 			lock_acquired = true;
  	}
  }
  
  /*
--- 336,402 ----
  	}
  }
  
! /*
!  * ResolveRecoveryConflictWithLock is called from ProcSleep()
!  * to resolve conflicts with other backends holding relation locks.
!  *
!  * The WaitLatch sleep normally done in ProcSleep()
!  * (when not InHotStandby) is performed here, for code clarity.
!  *
!  * We either resolve conflicts immediately or set a timeout to wake us at
!  * the limit of our patience.
!  *
!  * Resolve conflicts by cancelling to all backends holding a conflicting 
!  * lock.  As we are already queued to be granted the lock, no new lock
!  * requests conflicting with ours will be granted in the meantime.
!  *
!  * Deadlocks involving the Startup process and an ordinary backend process 
!  * will be detected by the deadlock detector within the ordinary backend.
!  */
! void
! ResolveRecoveryConflictWithLock(LOCKTAG locktag)
  {
! 	TimestampTz ltime;
  
! 	Assert(InHotStandby);
  
! 	ltime = GetStandbyLimitTime();
  
+ 	if (GetCurrentTimestamp() >= ltime)
+ 	{
+ 		/*
+ 		 * We're already behind, so clear a path as quickly as possible.
+ 		 */
+ 		VirtualTransactionId *backends;
+ 		backends = GetLockConflicts(&locktag, AccessExclusiveLock);
  		ResolveRecoveryConflictWithVirtualXIDs(backends,
  											 PROCSIG_RECOVERY_CONFLICT_LOCK);
+ 	}
+ 	else
+ 	{
+ 		/*
+ 		 * Wake up at ltime
+ 		 */
+ 		EnableTimeoutParams timeouts[1];
  
! 		timeouts[0].id = STANDBY_LOCK_TIMEOUT;
! 		timeouts[0].type = TMPARAM_AT;
! 		timeouts[0].fin_time = ltime;
! 		enable_timeouts(timeouts, 1);
  	}
+ 
+ 	/* Wait to be signaled by the release of the Relation Lock */
+ 	ProcWaitForSignal();
+ 
+ 	/*
+ 	 * Clear any timeout requests established above.  We assume here that the
+ 	 * Startup process doesn't have any other outstanding timeouts than what 
+ 	 * this function
+ 	 * uses.  If that stops being true, we could cancel the timeouts
+ 	 * individually, but that'd be slower.
+ 	 */
+ 	disable_all_timeouts(false);
+ 
  }
  
  /*
*************** StandbyTimeoutHandler(void)
*** 532,537 ****
--- 559,574 ----
  	SendRecoveryConflictWithBufferPin(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN);
  }
  
+ /*
+  * StandbyLockTimeoutHandler() will be called if STANDBY_LOCK_TIMEOUT is exceeded.
+  * This doesn't need to do anything, simply waking up is enough.
+  */
+ void
+ StandbyLockTimeoutHandler(void)
+ {
+ 	/* forget any pending STANDBY_DEADLOCK_TIMEOUT request */
+ 	disable_timeout(STANDBY_DEADLOCK_TIMEOUT, false);
+ }
  
  /*
   * -----------------------------------------------------
*************** StandbyTimeoutHandler(void)
*** 545,551 ****
   * process is the proxy by which the original locks are implemented.
   *
   * We only keep track of AccessExclusiveLocks, which are only ever held by
!  * one transaction on one relation, and don't worry about lock queuing.
   *
   * We keep a single dynamically expandible list of locks in local memory,
   * RelationLockList, so we can keep track of the various entries made by
--- 582,588 ----
   * process is the proxy by which the original locks are implemented.
   *
   * We only keep track of AccessExclusiveLocks, which are only ever held by
!  * one transaction on one relation.
   *
   * We keep a single dynamically expandible list of locks in local memory,
   * RelationLockList, so we can keep track of the various entries made by
*************** StandbyAcquireAccessExclusiveLock(Transa
*** 587,600 ****
  	newlock->relOid = relOid;
  	RecoveryLockList = lappend(RecoveryLockList, newlock);
  
- 	/*
- 	 * Attempt to acquire the lock as requested, if not resolve conflict
- 	 */
  	SET_LOCKTAG_RELATION(locktag, newlock->dbOid, newlock->relOid);
  
! 	if (LockAcquireExtended(&locktag, AccessExclusiveLock, true, true, false)
! 		== LOCKACQUIRE_NOT_AVAIL)
! 		ResolveRecoveryConflictWithLock(newlock->dbOid, newlock->relOid);
  }
  
  static void
--- 624,632 ----
  	newlock->relOid = relOid;
  	RecoveryLockList = lappend(RecoveryLockList, newlock);
  
  	SET_LOCKTAG_RELATION(locktag, newlock->dbOid, newlock->relOid);
  
! 	LockAcquireExtended(&locktag, AccessExclusiveLock, true, false, false);
  }
  
  static void
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
new file mode 100644
index 2c2535b..716477c
*** a/src/backend/storage/lmgr/proc.c
--- b/src/backend/storage/lmgr/proc.c
***************
*** 42,47 ****
--- 42,48 ----
  #include "postmaster/autovacuum.h"
  #include "replication/slot.h"
  #include "replication/syncrep.h"
+ #include "storage/standby.h"
  #include "storage/ipc.h"
  #include "storage/lmgr.h"
  #include "storage/pmsignal.h"
*************** ProcSleep(LOCALLOCK *locallock, LockMeth
*** 1090,1109 ****
  	 * If LockTimeout is set, also enable the timeout for that.  We can save a
  	 * few cycles by enabling both timeout sources in one call.
  	 */
! 	if (LockTimeout > 0)
  	{
! 		EnableTimeoutParams timeouts[2];
! 
! 		timeouts[0].id = DEADLOCK_TIMEOUT;
! 		timeouts[0].type = TMPARAM_AFTER;
! 		timeouts[0].delay_ms = DeadlockTimeout;
! 		timeouts[1].id = LOCK_TIMEOUT;
! 		timeouts[1].type = TMPARAM_AFTER;
! 		timeouts[1].delay_ms = LockTimeout;
! 		enable_timeouts(timeouts, 2);
  	}
- 	else
- 		enable_timeout_after(DEADLOCK_TIMEOUT, DeadlockTimeout);
  
  	/*
  	 * If somebody wakes us between LWLockRelease and WaitLatch, the latch
--- 1091,1113 ----
  	 * If LockTimeout is set, also enable the timeout for that.  We can save a
  	 * few cycles by enabling both timeout sources in one call.
  	 */
! 	if (!InHotStandby)
  	{
! 		if (LockTimeout > 0)
! 		{
! 			EnableTimeoutParams timeouts[2];
! 	
! 			timeouts[0].id = DEADLOCK_TIMEOUT;
! 			timeouts[0].type = TMPARAM_AFTER;
! 			timeouts[0].delay_ms = DeadlockTimeout;
! 			timeouts[1].id = LOCK_TIMEOUT;
! 			timeouts[1].type = TMPARAM_AFTER;
! 			timeouts[1].delay_ms = LockTimeout;
! 			enable_timeouts(timeouts, 2);
! 		}
! 		else
! 			enable_timeout_after(DEADLOCK_TIMEOUT, DeadlockTimeout);
  	}
  
  	/*
  	 * If somebody wakes us between LWLockRelease and WaitLatch, the latch
*************** ProcSleep(LOCALLOCK *locallock, LockMeth
*** 1121,1135 ****
  	 */
  	do
  	{
! 		WaitLatch(MyLatch, WL_LATCH_SET, 0);
! 		ResetLatch(MyLatch);
! 		/* check for deadlocks first, as that's probably log-worthy */
! 		if (got_deadlock_timeout)
  		{
! 			CheckDeadLock();
! 			got_deadlock_timeout = false;
  		}
- 		CHECK_FOR_INTERRUPTS();
  
  		/*
  		 * waitStatus could change from STATUS_WAITING to something else
--- 1125,1147 ----
  	 */
  	do
  	{
! 		if (InHotStandby)
  		{
! 			/* Set a timer and wait for that or for the Lock to be granted */
! 			ResolveRecoveryConflictWithLock(locallock->tag.lock);
! 		}
! 		else
! 		{
! 			WaitLatch(MyLatch, WL_LATCH_SET, 0);
! 			ResetLatch(MyLatch);
! 			/* check for deadlocks first, as that's probably log-worthy */
! 			if (got_deadlock_timeout)
! 			{
! 				CheckDeadLock();
! 				got_deadlock_timeout = false;
! 			}
! 			CHECK_FOR_INTERRUPTS();
  		}
  
  		/*
  		 * waitStatus could change from STATUS_WAITING to something else
diff --git a/src/include/storage/standby.h b/src/include/storage/standby.h
new file mode 100644
index 40b329b..b82406e
*** a/src/include/storage/standby.h
--- b/src/include/storage/standby.h
*************** extern void ResolveRecoveryConflictWithS
*** 33,42 ****
--- 33,44 ----
  extern void ResolveRecoveryConflictWithTablespace(Oid tsid);
  extern void ResolveRecoveryConflictWithDatabase(Oid dbid);
  
+ extern void ResolveRecoveryConflictWithLock(LOCKTAG locktag);
  extern void ResolveRecoveryConflictWithBufferPin(void);
  extern void CheckRecoveryConflictDeadlock(void);
  extern void StandbyDeadLockHandler(void);
  extern void StandbyTimeoutHandler(void);
+ extern void StandbyLockTimeoutHandler(void);
  
  /*
   * Standby Rmgr (RM_STANDBY_ID)
diff --git a/src/include/utils/timeout.h b/src/include/utils/timeout.h
new file mode 100644
index 30581a1..33b5016
*** a/src/include/utils/timeout.h
--- b/src/include/utils/timeout.h
*************** typedef enum TimeoutId
*** 29,34 ****
--- 29,35 ----
  	STATEMENT_TIMEOUT,
  	STANDBY_DEADLOCK_TIMEOUT,
  	STANDBY_TIMEOUT,
+ 	STANDBY_LOCK_TIMEOUT,
  	/* First user-definable timeout reason */
  	USER_TIMEOUT,
  	/* Maximum number of timeout reasons */
