Fix recent breakage of query-cancel logic, see my pghackers message
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 7 Jan 2001 04:17:29 +0000 (04:17 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 7 Jan 2001 04:17:29 +0000 (04:17 +0000)
of 6 Jan 2001 21:55.

src/backend/tcop/postgres.c
src/backend/utils/init/globals.c
src/include/miscadmin.h
src/include/utils/elog.h

index a8b7b4ec1bc2cfe87c9d50c7bdcea4f747877fd4..a73ba4df4abc1ba33cad7356e0c9f114f044998c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.198 2000/12/20 21:51:52 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.199 2001/01/07 04:17:29 tgl Exp $
  *
  * NOTES
  *   this is the "main" module of the postgres backend and
@@ -94,7 +94,7 @@ DLLIMPORT sigjmp_buf Warn_restart;
 
 bool       Warn_restart_ready = false;
 bool       InError = false;
-bool       ProcDiePending = false;
+volatile bool ProcDiePending = false;
 
 static bool EchoQuery = false; /* default don't echo */
 char       pg_pathname[MAXPGPATH];
@@ -920,7 +920,10 @@ finish_xact_command(void)
 void
 handle_warn(SIGNAL_ARGS)
 {
-   /* Don't joggle the elbow of a critical section */
+   /* Don't joggle the elbow of proc_exit */
+   if (proc_exit_inprogress)
+       return;
+   /* Don't joggle the elbow of a critical section, either */
    if (CritSectionCount > 0)
    {
        QueryCancel = true;
@@ -956,28 +959,38 @@ quickdie(SIGNAL_ARGS)
 void
 die(SIGNAL_ARGS)
 {
+   int         save_errno = errno;
+
    PG_SETMASK(&BlockSig);
 
-   /* Don't joggle the elbow of a critical section */
+   /* Don't joggle the elbow of proc_exit */
+   if (proc_exit_inprogress)
+   {
+       errno = save_errno;
+       return;
+   }
+   /* Don't joggle the elbow of a critical section, either */
    if (CritSectionCount > 0)
    {
-       QueryCancel = true;
        ProcDiePending = true;
+       errno = save_errno;
        return;
    }
-   /* Don't joggle the elbow of proc_exit, either */
-   if (proc_exit_inprogress)
-       return;
-   elog(FATAL, "The system is shutting down");
+   /* Otherwise force immediate proc_exit */
+   ForceProcDie();
 }
 
-/* signal handler for floating point exception */
-static void
-FloatExceptionHandler(SIGNAL_ARGS)
+/*
+ * This is split out of die() so that it can be invoked later from
+ * END_CRIT_CODE.
+ */
+void
+ForceProcDie(void)
 {
-   elog(ERROR, "floating point exception!"
-        " The last floating point operation either exceeded legal ranges"
-        " or was a divide by zero");
+   /* Reset flag to avoid another elog() during shutdown */
+   ProcDiePending = false;
+   /* Send error message and do proc_exit() */
+   elog(FATAL, "The system is shutting down");
 }
 
 /* signal handler for query cancel signal from postmaster */
@@ -986,22 +999,41 @@ QueryCancelHandler(SIGNAL_ARGS)
 {
    int         save_errno = errno;
 
+   /* Don't joggle the elbow of proc_exit, nor an already-in-progress abort */
+   if (proc_exit_inprogress || InError)
+   {
+       errno = save_errno;
+       return;
+   }
+
+   /* Set flag to cause CancelQuery to be called when it's safe */
    QueryCancel = true;
+
+   /* If we happen to be waiting for a lock, get out of that */
    LockWaitCancel();
+
+   /* Otherwise, bide our time... */
    errno = save_errno;
 }
 
 void
 CancelQuery(void)
 {
-
-   /*
-    * QueryCancel flag will be reset in main loop, which we reach by
-    * longjmp from elog().
-    */
+   /* Reset flag to avoid another elog() during error recovery */
+   QueryCancel = false;
+   /* Create an artificial error condition to get out of query */
    elog(ERROR, "Query was cancelled.");
 }
 
+/* signal handler for floating point exception */
+static void
+FloatExceptionHandler(SIGNAL_ARGS)
+{
+   elog(ERROR, "floating point exception!"
+        " The last floating point operation either exceeded legal ranges"
+        " or was a divide by zero");
+}
+
 static void
 SigHupHandler(SIGNAL_ARGS)
 {
@@ -1651,7 +1683,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
    if (!IsUnderPostmaster)
    {
        puts("\nPOSTGRES backend interactive interface ");
-       puts("$Revision: 1.198 $ $Date: 2000/12/20 21:51:52 $\n");
+       puts("$Revision: 1.199 $ $Date: 2001/01/07 04:17:29 $\n");
    }
 
    /*
index e6b57c648b374b0375d330ecfb82417a9834267e..4359ef60a88f3d874bfc30e7b336cf67223bff9e 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.48 2000/12/28 13:00:24 vadim Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.49 2001/01/07 04:17:29 tgl Exp $
  *
  * NOTES
  *   Globals used all over the place should be declared here and not
@@ -34,7 +34,7 @@ ProtocolVersion FrontendProtocol = PG_PROTOCOL_LATEST;
 
 bool       Noversion = false;
 bool       Quiet = false;
-bool       QueryCancel = false;
+volatile bool QueryCancel = false;
 
 int            MyProcPid;
 struct Port *MyProcPort;
index f41a01822ac8b3e04f863e3ee8dfb8b82857f8d3..6b5dff9478ad6c4e1bf8529a399539e09f2a2cb8 100644 (file)
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: miscadmin.h,v 1.75 2000/11/29 20:59:54 tgl Exp $
+ * $Id: miscadmin.h,v 1.76 2001/01/07 04:17:28 tgl Exp $
  *
  * NOTES
  *   some of the information in this file will be moved to
@@ -42,7 +42,7 @@ extern int    PostmasterMain(int argc, char *argv[]);
  */
 extern bool Noversion;
 extern bool Quiet;
-extern bool QueryCancel;
+extern volatile bool QueryCancel;
 extern char *DataDir;
 
 extern int MyProcPid;
index 37db2c7aaf84c5e3025af0805f40dd90606fb4d1..e7305d67fc266bd18df746530de43508c3f938d7 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: elog.h,v 1.21 2000/12/18 00:44:50 tgl Exp $
+ * $Id: elog.h,v 1.22 2001/01/07 04:17:28 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -30,11 +30,13 @@ extern int Use_syslog;
 /*
  * If CritSectionCount > 0, signal handlers mustn't do
  * elog(ERROR|FATAL), instead remember what action is
- * required with QueryCancel & ProcDiePending.
+ * required with QueryCancel or ProcDiePending.
+ * ProcDiePending will be honored at critical section exit,
+ * but QueryCancel is only checked at specified points.
  */
 extern uint32 CritSectionCount;    /* duplicates access/xlog.h */
-extern bool QueryCancel;       /* duplicates miscadmin.h */
-extern bool    ProcDiePending;
+extern volatile bool ProcDiePending;
+extern void ForceProcDie(void);    /* in postgres.c */
 
 #define    START_CRIT_CODE     (CritSectionCount++)
 
@@ -43,13 +45,8 @@ extern bool  ProcDiePending;
        if (CritSectionCount == 0) \
            elog(STOP, "Not in critical section"); \
        CritSectionCount--; \
-       if (CritSectionCount == 0 && QueryCancel) \
-       { \
-           if (ProcDiePending) \
-               elog(FATAL, "The system is shutting down"); \
-           else \
-               elog(ERROR, "Query was cancelled."); \
-       } \
+       if (CritSectionCount == 0 && ProcDiePending) \
+           ForceProcDie(); \
    } while(0)
 
 extern bool Log_timestamp;