From 10af02b912714a1cb423d100186b43b20142f008 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Fri, 29 Jun 2007 17:07:39 +0000
Subject: [PATCH] Arrange for SIGINT in autovacuum workers to cancel the
 current table and continue with the schedule.  Change current uses of SIGINT
 to abort a worker into SIGTERM, which keeps the old behaviour of terminating
 the process.

Patch from ITAGAKI Takahiro, with some editorializing of my own.
---
 src/backend/postmaster/autovacuum.c | 56 +++++++++++++++++++++++++----
 src/backend/postmaster/postmaster.c |  4 +--
 src/backend/storage/ipc/procarray.c |  4 +--
 src/backend/tcop/postgres.c         | 14 +++++---
 4 files changed, 63 insertions(+), 15 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index bc2dfee28fc..2739e2484fd 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -55,7 +55,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.51 2007/06/25 16:09:03 alvherre Exp $
+ *	  $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.52 2007/06/29 17:07:39 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -75,6 +75,7 @@
 #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"
@@ -2025,12 +2026,53 @@ next_worker:
 		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);
+		/*
+		 * We will abort vacuuming the current table if we are interrupted, and
+		 * continue with the next one in schedule; but if anything else
+		 * happens, we will do our usual error handling which is to cause the
+		 * worker process to exit.
+		 */
+		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;
+
+			MemoryContextSwitchTo(TopTransactionContext);
+			errdata = CopyErrorData();
+
+			/*
+			 * If we errored out due to a cancel request, abort and restart the
+			 * transaction and go to the next table.  Otherwise rethrow the
+			 * error so that the outermost handler deals with it.
+			 */
+			if (errdata->sqlerrcode == ERRCODE_QUERY_CANCELED)
+			{
+				HOLD_INTERRUPTS();
+				elog(LOG, "cancelling autovacuum of table \"%s.%s.%s\"",
+					 get_database_name(MyDatabaseId),
+					 get_namespace_name(get_rel_namespace(tab->at_relid)),
+					 get_rel_name(tab->at_relid));
+
+				AbortOutOfAnyTransaction();
+				FlushErrorState();
+
+				/* restart our transaction for the following operations */
+				StartTransactionCommand();
+				RESUME_INTERRUPTS();
+			}
+			else
+				PG_RE_THROW();
+		}
+		PG_END_TRY();
+
 		/* be tidy */
 		pfree(tab);
 	}
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index cb060878a92..e68546e3e8d 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.528 2007/06/25 16:09:03 alvherre Exp $
+ *	  $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.529 2007/06/29 17:07:39 alvherre Exp $
  *
  * NOTES
  *
@@ -1875,7 +1875,7 @@ pmdie(SIGNAL_ARGS)
 
 			/* autovacuum workers are shut down immediately */
 			if (DLGetHead(BackendList))
-				SignalSomeChildren(SIGINT, true);
+				SignalSomeChildren(SIGTERM, true);
 
 			if (DLGetHead(BackendList))
 				break;			/* let reaper() handle this */
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index 9d290ba9739..9819adffcbb 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -23,7 +23,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.26 2007/06/07 21:45:59 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.27 2007/06/29 17:07:39 alvherre Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1008,7 +1008,7 @@ CheckOtherDBBackends(Oid databaseId)
 				 */
 				LWLockRelease(ProcArrayLock);
 
-				(void) kill(autopid, SIGINT);		/* ignore any error */
+				(void) kill(autopid, SIGTERM);		/* ignore any error */
 
 				break;
 			}
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 94fd65e5d44..c5ede140042 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.534 2007/06/23 22:12:52 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.535 2007/06/29 17:07:39 alvherre Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -51,6 +51,7 @@
 #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"
@@ -2540,9 +2541,14 @@ ProcessInterrupts(void)
 		ImmediateInterruptOK = false;	/* not idle anymore */
 		DisableNotifyInterrupt();
 		DisableCatchupInterrupt();
-		ereport(FATAL,
-				(errcode(ERRCODE_ADMIN_SHUTDOWN),
-			 errmsg("terminating connection due to administrator command")));
+		if (IsAutoVacuumWorkerProcess())
+			ereport(FATAL,
+					(errcode(ERRCODE_ADMIN_SHUTDOWN),
+					 errmsg("terminating autovacuum process due to administrator command")));
+		else
+			ereport(FATAL,
+					(errcode(ERRCODE_ADMIN_SHUTDOWN),
+					 errmsg("terminating connection due to administrator command")));
 	}
 	if (QueryCancelPending)
 	{
-- 
GitLab