Arrange for SIGINT in autovacuum workers to cancel the current table and
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Fri, 29 Jun 2007 17:07:39 +0000 (17:07 +0000)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Fri, 29 Jun 2007 17:07:39 +0000 (17:07 +0000)
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
src/backend/postmaster/postmaster.c
src/backend/storage/ipc/procarray.c
src/backend/tcop/postgres.c

index bc2dfee28fc5b46aae45c79e69a3e360f976dd5c..2739e2484fd0dd1ef0f8539bb101473b0d5546d4 100644 (file)
@@ -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);
    }
index cb060878a92a8e19a70925e180a9edfad3d73b42..e68546e3e8de34d238fd0fab87ea32f410b8e120 100644 (file)
@@ -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 */
index 9d290ba97393460fd2416e132e71b33b3349b69e..9819adffcbb6c0c587248eb7e54bac841be26d3a 100644 (file)
@@ -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;
            }
index 94fd65e5d448cf3e691964c6cd24538565b0d688..c5ede140042cacdbe1512f655b1819756e61b299 100644 (file)
@@ -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)
    {