diff -cpr autovacuum-procs-2/src/backend/commands/cluster.c cancel_autovac_on_drop/src/backend/commands/cluster.c
*** autovacuum-procs-2/src/backend/commands/cluster.c	Sat May 19 10:02:34 2007
--- cancel_autovac_on_drop/src/backend/commands/cluster.c	Fri Jun 22 10:51:58 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 autovacuum-procs-2/src/backend/commands/tablecmds.c cancel_autovac_on_drop/src/backend/commands/tablecmds.c
*** autovacuum-procs-2/src/backend/commands/tablecmds.c	Mon Jun  4 07:16:03 2007
--- cancel_autovac_on_drop/src/backend/commands/tablecmds.c	Fri Jun 22 10:51:58 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 autovacuum-procs-2/src/backend/postmaster/autovacuum.c cancel_autovac_on_drop/src/backend/postmaster/autovacuum.c
*** autovacuum-procs-2/src/backend/postmaster/autovacuum.c	Fri Jun 22 10:51:45 2007
--- cancel_autovac_on_drop/src/backend/postmaster/autovacuum.c	Fri Jun 22 10:51:58 2007
***************
*** 66,71 ****
--- 66,72 ----
  #include "catalog/namespace.h"
  #include "catalog/pg_autovacuum.h"
  #include "catalog/pg_database.h"
+ #include "commands/dbcommands.h"
  #include "commands/vacuum.h"
  #include "libpq/hba.h"
  #include "libpq/pqsignal.h"
*************** next_worker:
*** 2017,2028 ****
  		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);
  	}
--- 2018,2073 ----
  		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. */
! 			switch (errdata->sqlerrcode)
! 			{
! 				case ERRCODE_QUERY_CANCELED:
! 					elog(LOG, "autovacuum on %s.%s.%s is canceled",
! 						get_database_name(MyDatabaseId),
! 						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);
! 					break;
! 				case ERRCODE_ADMIN_SHUTDOWN:
! 					elog(LOG, "autovacuum on %s is canceled",
! 						get_database_name(MyDatabaseId));
! 					HOLD_INTERRUPTS();
! 					FlushErrorState();
! 					proc_exit(0);
! 					break;
! 				default:
! 					MemoryContextSwitchTo(ecxt);
! 					PG_RE_THROW();
! 					break;
! 			}
! 		}
! 		PG_END_TRY();
! 
  		/* be tidy */
  		pfree(tab);
  	}
*************** AutoVacuumShmemInit(void)
*** 2638,2641 ****
--- 2683,2725 ----
  	}
  	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 autovacuum-procs-2/src/backend/postmaster/postmaster.c cancel_autovac_on_drop/src/backend/postmaster/postmaster.c
*** autovacuum-procs-2/src/backend/postmaster/postmaster.c	Fri Jun 22 10:51:45 2007
--- cancel_autovac_on_drop/src/backend/postmaster/postmaster.c	Fri Jun 22 10:51:58 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 autovacuum-procs-2/src/backend/storage/ipc/procarray.c cancel_autovac_on_drop/src/backend/storage/ipc/procarray.c
*** autovacuum-procs-2/src/backend/storage/ipc/procarray.c	Fri Jun  8 06:45:59 2007
--- cancel_autovac_on_drop/src/backend/storage/ipc/procarray.c	Fri Jun 22 10:51:58 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 autovacuum-procs-2/src/backend/tcop/postgres.c cancel_autovac_on_drop/src/backend/tcop/postgres.c
*** autovacuum-procs-2/src/backend/tcop/postgres.c	Tue May  1 01:37:08 2007
--- cancel_autovac_on_drop/src/backend/tcop/postgres.c	Fri Jun 22 10:51:58 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,2559 ----
  		ImmediateInterruptOK = false;	/* not idle anymore */
  		DisableNotifyInterrupt();
  		DisableCatchupInterrupt();
! 		ereport((IsAutoVacuumWorkerProcess() ? ERROR : FATAL),
  				(errcode(ERRCODE_ADMIN_SHUTDOWN),
  			 errmsg("terminating connection due to administrator command")));
  	}
diff -cpr autovacuum-procs-2/src/backend/tcop/utility.c cancel_autovac_on_drop/src/backend/tcop/utility.c
*** autovacuum-procs-2/src/backend/tcop/utility.c	Thu May 31 05:12:01 2007
--- cancel_autovac_on_drop/src/backend/tcop/utility.c	Fri Jun 22 10:51:58 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 autovacuum-procs-2/src/include/postmaster/autovacuum.h cancel_autovac_on_drop/src/include/postmaster/autovacuum.h
*** autovacuum-procs-2/src/include/postmaster/autovacuum.h	Fri Jun 22 10:51:45 2007
--- cancel_autovac_on_drop/src/include/postmaster/autovacuum.h	Fri Jun 22 10:51:58 2007
*************** extern void AutoVacWorkerFailed(void);
*** 48,53 ****
--- 48,55 ----
  /* 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[]);