diff -cpr head/src/backend/commands/cluster.c cancel_autovac_on_drop/src/backend/commands/cluster.c
*** head/src/backend/commands/cluster.c	Sat May 19 10:02:34 2007
--- cancel_autovac_on_drop/src/backend/commands/cluster.c	Wed Jun 20 11:38:29 2007
***************
*** 31,36 ****
--- 31,37 ----
  #include "catalog/toasting.h"
  #include "commands/cluster.h"
  #include "commands/vacuum.h"
+ #include "postmaster/autovacuum.h"
  #include "miscadmin.h"
  #include "storage/procarray.h"
  #include "utils/acl.h"
*************** cluster(ClusterStmt *stmt, bool isTopLev
*** 96,105 ****
  		Relation	rel;
  		RelToCluster rvtc;
  
! 		/* Find and lock the table */
! 		rel = heap_openrv(stmt->relation, AccessExclusiveLock);
  
! 		tableOid = RelationGetRelid(rel);
  
  		/* Check permissions */
  		if (!pg_class_ownercheck(tableOid, GetUserId()))
--- 97,107 ----
  		Relation	rel;
  		RelToCluster rvtc;
  
! 		tableOid = RangeVarGetRelid(stmt->relation, false);
! 		AutoVacuumCancel(MyDatabaseId, tableOid);
  
! 		/* Find and lock the table */
! 		rel = heap_open(tableOid, AccessExclusiveLock);
  
  		/* Check permissions */
  		if (!pg_class_ownercheck(tableOid, GetUserId()))
diff -cpr head/src/backend/commands/tablecmds.c cancel_autovac_on_drop/src/backend/commands/tablecmds.c
*** head/src/backend/commands/tablecmds.c	Mon Jun  4 07:16:03 2007
--- cancel_autovac_on_drop/src/backend/commands/tablecmds.c	Wed Jun 20 11:38:29 2007
***************
*** 53,58 ****
--- 53,59 ----
  #include "parser/parse_relation.h"
  #include "parser/parse_type.h"
  #include "parser/parser.h"
+ #include "postmaster/autovacuum.h"
  #include "rewrite/rewriteDefine.h"
  #include "rewrite/rewriteHandler.h"
  #include "storage/smgr.h"
*************** ExecuteTruncate(TruncateStmt *stmt)
*** 541,549 ****
  	foreach(cell, stmt->relations)
  	{
  		RangeVar   *rv = lfirst(cell);
  		Relation	rel;
  
! 		rel = heap_openrv(rv, AccessExclusiveLock);
  		truncate_check_rel(rel);
  		rels = lappend(rels, rel);
  		relids = lappend_oid(relids, RelationGetRelid(rel));
--- 542,553 ----
  	foreach(cell, stmt->relations)
  	{
  		RangeVar   *rv = lfirst(cell);
+ 		Oid			relid;
  		Relation	rel;
  
! 		relid = RangeVarGetRelid(rv, false);
! 		AutoVacuumCancel(MyDatabaseId, relid);
! 		rel = heap_open(relid, AccessExclusiveLock);
  		truncate_check_rel(rel);
  		rels = lappend(rels, rel);
  		relids = lappend_oid(relids, RelationGetRelid(rel));
*************** ExecuteTruncate(TruncateStmt *stmt)
*** 572,577 ****
--- 576,582 ----
  				Oid			relid = lfirst_oid(cell);
  				Relation	rel;
  
+ 				AutoVacuumCancel(MyDatabaseId, relid);
  				rel = heap_open(relid, AccessExclusiveLock);
  				ereport(NOTICE,
  						(errmsg("truncate cascades to table \"%s\"",
diff -cpr head/src/backend/postmaster/autovacuum.c cancel_autovac_on_drop/src/backend/postmaster/autovacuum.c
*** head/src/backend/postmaster/autovacuum.c	Thu Jun 14 06:24:55 2007
--- cancel_autovac_on_drop/src/backend/postmaster/autovacuum.c	Wed Jun 20 11:38:29 2007
*************** next_worker:
*** 1960,1971 ****
  		autovac_balance_cost();
  		LWLockRelease(AutovacuumLock);
  
! 		/* have at it */
! 		autovacuum_do_vac_analyze(tab->at_relid,
! 								  tab->at_dovacuum,
! 								  tab->at_doanalyze,
! 								  tab->at_freeze_min_age,
! 								  bstrategy);
  		/* be tidy */
  		pfree(tab);
  	}
--- 1960,2006 ----
  		autovac_balance_cost();
  		LWLockRelease(AutovacuumLock);
  
! 		PG_TRY();
! 		{
! 			/* have at it */
! 			autovacuum_do_vac_analyze(tab->at_relid,
! 									  tab->at_dovacuum,
! 									  tab->at_doanalyze,
! 									  tab->at_freeze_min_age,
! 									  bstrategy);
! 		}
! 		PG_CATCH();
! 		{
! 			ErrorData	   *errdata;
! 			MemoryContext	ecxt;
! 
! 			ecxt = MemoryContextSwitchTo(TopTransactionContext);
! 			errdata = CopyErrorData();
! 
! 			/* Cancel current table and go next. */
! 			if (errdata->sqlerrcode == ERRCODE_QUERY_CANCELED)
! 			{
! 				elog(DEBUG1, "autovacuum on relation %s.%s is canceled",
! 					get_namespace_name(get_rel_namespace(tab->at_relid)),
! 					get_rel_name(tab->at_relid));
! 
! 				HOLD_INTERRUPTS();
! 				AbortCurrentTransaction();
! 				FlushErrorState();
! 				RESUME_INTERRUPTS();
! 
! 				/* Restart transaction for next operations. */
! 				StartTransactionCommand();
! 				MemoryContextSwitchTo(AutovacMemCxt);
! 			}
! 			else
! 			{
! 				MemoryContextSwitchTo(ecxt);
! 				PG_RE_THROW();
! 			}
! 		}
! 		PG_END_TRY();
! 
  		/* be tidy */
  		pfree(tab);
  	}
*************** AutoVacuumShmemInit(void)
*** 2581,2584 ****
--- 2616,2658 ----
  	}
  	else
  		Assert(found);
+ }
+ 
+ /*
+  * AutoVacuumCancel -- SIGINT to autovacuums running on the given relation.
+  *
+  *	Return a pid of the killed autovacuum worker process, or zero.
+  */
+ int
+ AutoVacuumCancel(Oid dbid, Oid relid)
+ {
+ 	WorkerInfo	worker;
+ 	pid_t		pid = 0;
+ 
+ 	LWLockAcquire(AutovacuumLock, LW_SHARED);
+ 
+ 	worker = (WorkerInfo) SHMQueueNext(&AutoVacuumShmem->av_runningWorkers,
+ 										&AutoVacuumShmem->av_runningWorkers,
+ 										offsetof(WorkerInfoData, wi_links));
+ 	while (worker)
+ 	{
+ 		if (worker->wi_dboid == dbid &&
+ 			worker->wi_tableoid == relid &&
+ 			worker->wi_workerpid != MyProcPid)
+ 		{
+ 			pid = worker->wi_workerpid;
+ 			break;
+ 		}
+ 
+ 		worker = (WorkerInfo) SHMQueueNext(&AutoVacuumShmem->av_runningWorkers,
+ 											&worker->wi_links,
+ 											offsetof(WorkerInfoData, wi_links));
+ 	}
+ 	LWLockRelease(AutovacuumLock);
+ 
+ 	/* kill the worker */
+ 	if (pid != 0)
+ 		(void) kill(pid, SIGINT);
+ 
+ 	return pid;
  }
diff -cpr head/src/backend/postmaster/postmaster.c cancel_autovac_on_drop/src/backend/postmaster/postmaster.c
*** head/src/backend/postmaster/postmaster.c	Fri Mar 23 04:53:30 2007
--- cancel_autovac_on_drop/src/backend/postmaster/postmaster.c	Wed Jun 20 11:38:29 2007
*************** pmdie(SIGNAL_ARGS)
*** 1875,1881 ****
  
  			/* autovacuum workers are shut down immediately */
  			if (DLGetHead(BackendList))
! 				SignalSomeChildren(SIGINT, true);
  
  			if (DLGetHead(BackendList))
  				break;			/* let reaper() handle this */
--- 1875,1881 ----
  
  			/* autovacuum workers are shut down immediately */
  			if (DLGetHead(BackendList))
! 				SignalSomeChildren(SIGTERM, true);
  
  			if (DLGetHead(BackendList))
  				break;			/* let reaper() handle this */
diff -cpr head/src/backend/storage/ipc/procarray.c cancel_autovac_on_drop/src/backend/storage/ipc/procarray.c
*** head/src/backend/storage/ipc/procarray.c	Fri Jun  8 06:45:59 2007
--- cancel_autovac_on_drop/src/backend/storage/ipc/procarray.c	Wed Jun 20 11:38:29 2007
*************** CheckOtherDBBackends(Oid databaseId)
*** 1008,1014 ****
  				 */
  				LWLockRelease(ProcArrayLock);
  
! 				(void) kill(autopid, SIGINT);		/* ignore any error */
  
  				break;
  			}
--- 1008,1014 ----
  				 */
  				LWLockRelease(ProcArrayLock);
  
! 				(void) kill(autopid, SIGTERM);		/* ignore any error */
  
  				break;
  			}
diff -cpr head/src/backend/tcop/postgres.c cancel_autovac_on_drop/src/backend/tcop/postgres.c
*** head/src/backend/tcop/postgres.c	Tue May  1 01:37:08 2007
--- cancel_autovac_on_drop/src/backend/tcop/postgres.c	Wed Jun 20 11:38:29 2007
***************
*** 51,56 ****
--- 51,57 ----
  #include "optimizer/planner.h"
  #include "parser/analyze.h"
  #include "parser/parser.h"
+ #include "postmaster/autovacuum.h"
  #include "rewrite/rewriteHandler.h"
  #include "storage/freespace.h"
  #include "storage/ipc.h"
*************** ProcessInterrupts(void)
*** 2552,2558 ****
  		ImmediateInterruptOK = false;	/* not idle anymore */
  		DisableNotifyInterrupt();
  		DisableCatchupInterrupt();
! 		ereport(FATAL,
  				(errcode(ERRCODE_ADMIN_SHUTDOWN),
  			 errmsg("terminating connection due to administrator command")));
  	}
--- 2553,2564 ----
  		ImmediateInterruptOK = false;	/* not idle anymore */
  		DisableNotifyInterrupt();
  		DisableCatchupInterrupt();
! 		if (IsAutoVacuumWorkerProcess())
! 			ereport(FATAL,
! 				(errcode(ERRCODE_ADMIN_SHUTDOWN),
! 			 errmsg("terminating autovacuum due to administrator command")));
! 		else
! 			ereport(FATAL,
  				(errcode(ERRCODE_ADMIN_SHUTDOWN),
  			 errmsg("terminating connection due to administrator command")));
  	}
diff -cpr head/src/backend/tcop/utility.c cancel_autovac_on_drop/src/backend/tcop/utility.c
*** head/src/backend/tcop/utility.c	Thu May 31 05:12:01 2007
--- cancel_autovac_on_drop/src/backend/tcop/utility.c	Wed Jun 20 11:38:29 2007
***************
*** 46,51 ****
--- 46,52 ----
  #include "commands/view.h"
  #include "miscadmin.h"
  #include "parser/analyze.h"
+ #include "postmaster/autovacuum.h"
  #include "postmaster/bgwriter.h"
  #include "rewrite/rewriteDefine.h"
  #include "rewrite/rewriteRemove.h"
*************** ProcessUtility(Node *parsetree,
*** 584,590 ****
--- 585,595 ----
  							rel = makeRangeVarFromNameList(names);
  							if (CheckDropPermissions(rel, RELKIND_RELATION,
  													 stmt->missing_ok))
+ 							{
+ 								AutoVacuumCancel(MyDatabaseId,
+ 									RangeVarGetRelid(rel, false));
  								RemoveRelation(rel, stmt->behavior);
+ 							}
  							break;
  
  						case OBJECT_SEQUENCE:
diff -cpr head/src/include/postmaster/autovacuum.h cancel_autovac_on_drop/src/include/postmaster/autovacuum.h
*** head/src/include/postmaster/autovacuum.h	Thu Apr 19 01:44:18 2007
--- cancel_autovac_on_drop/src/include/postmaster/autovacuum.h	Wed Jun 20 11:38:29 2007
*************** extern int	StartAutoVacWorker(void);
*** 46,51 ****
--- 46,53 ----
  /* autovacuum cost-delay balancer */
  extern void AutoVacuumUpdateDelay(void);
  
+ extern int	AutoVacuumCancel(Oid dbid, Oid relid);
+ 
  #ifdef EXEC_BACKEND
  extern void AutoVacLauncherMain(int argc, char *argv[]);
  extern void AutoVacWorkerMain(int argc, char *argv[]);
