Index: src/backend/storage/lmgr/deadlock.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/storage/lmgr/deadlock.c,v
retrieving revision 1.48
diff -c -p -r1.48 deadlock.c
*** src/backend/storage/lmgr/deadlock.c	19 Jun 2007 20:13:21 -0000	1.48
--- src/backend/storage/lmgr/deadlock.c	25 Oct 2007 20:06:36 -0000
*************** static int	maxPossibleConstraints;
*** 109,114 ****
--- 109,117 ----
  static DEADLOCK_INFO *deadlockDetails;
  static int	nDeadlockDetails;
  
+ /* PGPROC pointer of any blocking av worker found */
+ static PGPROC *blocking_autovacuum_proc = NULL; 
+ 
  
  /*
   * InitDeadLockChecking -- initialize deadlock checker during backend startup
*************** DeadLockCheck(PGPROC *proc)
*** 206,211 ****
--- 209,217 ----
  	nPossibleConstraints = 0;
  	nWaitOrders = 0;
  
+ 	/* Initialize to not blocked by an autovacuum worker */
+ 	blocking_autovacuum_proc = NULL;
+ 
  	/* Search for deadlocks and possible fixes */
  	if (DeadLockCheckRecurse(proc))
  	{
*************** DeadLockCheck(PGPROC *proc)
*** 255,265 ****
--- 261,289 ----
  	/* Return code tells caller if we had to escape a deadlock or not */
  	if (nWaitOrders > 0)
  		return DS_SOFT_DEADLOCK;
+ 	else if (blocking_autovacuum_proc != NULL)
+ 		return DS_BLOCKED_BY_AUTOVACUUM;
  	else
  		return DS_NO_DEADLOCK;
  }
  
  /*
+  * Return the PGPROC of the autovacuum that's blocking a process.
+  *
+  * We reset the saved pointer as soon as we pass it back.
+  */
+ PGPROC *
+ GetBlockingAutoVacuumPgproc(void)
+ {
+ 	PGPROC	*ptr;
+ 
+ 	ptr = blocking_autovacuum_proc;
+ 	blocking_autovacuum_proc = NULL;
+ 
+ 	return ptr;
+ }
+ 
+ /*
   * DeadLockCheckRecurse -- recursively search for valid orderings
   *
   * curConstraints[] holds the current set of constraints being considered
*************** FindLockCycleRecurse(PGPROC *checkProc,
*** 497,502 ****
--- 521,534 ----
  				if ((proclock->holdMask & LOCKBIT_ON(lm)) &&
  					(conflictMask & LOCKBIT_ON(lm)))
  				{
+ 					/*
+ 					 * Look for a blocking autovacuum. There will only ever
+ 					 * be one, since the autovacuum workers are careful
+ 					 * not to operate concurrently on the same table. 
+ 					 */
+ 					if (proc->vacuumFlags & PROC_IS_AUTOVACUUM)
+ 						blocking_autovacuum_proc = proc;
+ 
  					/* This proc hard-blocks checkProc */
  					if (FindLockCycleRecurse(proc, depth + 1,
  											 softEdges, nSoftEdges))
Index: src/backend/storage/lmgr/proc.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/storage/lmgr/proc.c,v
retrieving revision 1.195
diff -c -p -r1.195 proc.c
*** src/backend/storage/lmgr/proc.c	24 Oct 2007 20:55:36 -0000	1.195
--- src/backend/storage/lmgr/proc.c	25 Oct 2007 20:03:58 -0000
*************** ProcSleep(LOCALLOCK *locallock, LockMeth
*** 734,739 ****
--- 734,740 ----
  	PROC_QUEUE *waitQueue = &(lock->waitProcs);
  	LOCKMASK	myHeldLocks = MyProc->heldLocks;
  	bool		early_deadlock = false;
+ 	bool 		allow_autovacuum_cancel = true;
  	int			myWaitStatus;
  	PGPROC	   *proc;
  	int			i;
*************** ProcSleep(LOCALLOCK *locallock, LockMeth
*** 894,899 ****
--- 895,949 ----
  		myWaitStatus = MyProc->waitStatus;
  
  		/*
+ 		 * If we are not deadlocked, but are waiting on an autovacuum-induced
+ 		 * task, send a signal to interrupt it.  
+ 		 */
+ 		if (deadlock_state == DS_BLOCKED_BY_AUTOVACUUM && allow_autovacuum_cancel)
+ 		{
+ 			PGPROC	*autovac = GetBlockingAutoVacuumPgproc();
+ 
+ 			LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
+ 
+ 			/*
+ 			 * only do it if the worker is not working to protect against Xid
+ 			 * wraparound 
+ 			 */
+ 			if ((autovac != NULL) &&
+ 				!(autovac->vacuumFlags & PROC_VACUUM_FOR_WRAPAROUND))
+ 			{
+ 				int		pid = autovac->pid;
+ 
+ 				elog(DEBUG2, "sending cancel to blocking autovacuum pid = %d",
+ 					 pid);
+ 
+ 				/* don't hold the lock across the kill() syscall */
+ 				LWLockRelease(ProcArrayLock);
+ 
+ 				/*
+ 				 * Send the autovacuum worker Back to Old Kent Road
+ 				 *
+ 				 * If we have setsid(), signal the backend's whole process group 
+ 				 */
+ #ifdef HAVE_SETSID
+ 				if (kill(-pid, SIGINT))
+ #else
+ 					if (kill(pid, SIGINT))
+ #endif
+ 					{
+ 						/* Just a warning to allow multiple callers */
+ 						ereport(WARNING,
+ 								(errmsg("could not send signal to process %d: %m",
+ 										pid)));
+ 					}
+ 			}
+ 			else
+ 				LWLockRelease(ProcArrayLock);
+ 
+ 			/* prevent signal from being resent more than once */
+ 			allow_autovacuum_cancel = false;
+ 		}
+ 
+ 		/*
  		 * If awoken after the deadlock check interrupt has run, and
  		 * log_lock_waits is on, then report about the wait.
  		 */
*************** CheckDeadLock(void)
*** 1189,1201 ****
  		 * RemoveFromWaitQueue took care of waking up any such processes.
  		 */
  	}
! 	else if (log_lock_waits)
  	{
  		/*
  		 * Unlock my semaphore so that the interrupted ProcSleep() call can
  		 * print the log message (we daren't do it here because we are inside
  		 * a signal handler).  It will then sleep again until someone
  		 * releases the lock.
  		 */
  		PGSemaphoreUnlock(&MyProc->sem);
  	}
--- 1239,1254 ----
  		 * RemoveFromWaitQueue took care of waking up any such processes.
  		 */
  	}
! 	else if (log_lock_waits || deadlock_state == DS_BLOCKED_BY_AUTOVACUUM)
  	{
  		/*
  		 * Unlock my semaphore so that the interrupted ProcSleep() call can
  		 * print the log message (we daren't do it here because we are inside
  		 * a signal handler).  It will then sleep again until someone
  		 * releases the lock.
+ 		 *
+ 		 * If blocked by autovacuum, this wakeup will enable ProcSleep to send
+ 		 * the cancelling signal to the autovacuum worker.
  		 */
  		PGSemaphoreUnlock(&MyProc->sem);
  	}
Index: src/include/storage/lock.h
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/include/storage/lock.h,v
retrieving revision 1.107
diff -c -p -r1.107 lock.h
*** src/include/storage/lock.h	5 Sep 2007 18:10:48 -0000	1.107
--- src/include/storage/lock.h	25 Oct 2007 17:11:02 -0000
*************** typedef enum
*** 442,448 ****
  	DS_NOT_YET_CHECKED,			/* no deadlock check has run yet */
  	DS_NO_DEADLOCK,				/* no deadlock detected */
  	DS_SOFT_DEADLOCK,			/* deadlock avoided by queue rearrangement */
! 	DS_HARD_DEADLOCK			/* deadlock, no way out but ERROR */
  } DeadLockState;
  
  
--- 442,449 ----
  	DS_NOT_YET_CHECKED,			/* no deadlock check has run yet */
  	DS_NO_DEADLOCK,				/* no deadlock detected */
  	DS_SOFT_DEADLOCK,			/* deadlock avoided by queue rearrangement */
! 	DS_HARD_DEADLOCK,			/* deadlock, no way out but ERROR */
! 	DS_BLOCKED_BY_AUTOVACUUM	/* queue blocked by autovacuum worker */
  } DeadLockState;
  
  
*************** extern void lock_twophase_postabort(Tran
*** 495,500 ****
--- 496,502 ----
  						void *recdata, uint32 len);
  
  extern DeadLockState DeadLockCheck(PGPROC *proc);
+ extern PGPROC *GetBlockingAutoVacuumPgproc(void);
  extern void DeadLockReport(void);
  extern void RememberSimpleDeadLock(PGPROC *proc1,
  					   LOCKMODE lockmode,
