From cb7ce7d0e30d208e612da634936dec0b53f78324 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 7 Jan 2001 04:17:29 +0000 Subject: [PATCH] Fix recent breakage of query-cancel logic, see my pghackers message of 6 Jan 2001 21:55. --- src/backend/tcop/postgres.c | 74 ++++++++++++++++++++++++++++------------ src/backend/utils/init/globals.c | 4 +-- src/include/miscadmin.h | 4 +-- src/include/utils/elog.h | 19 +++++------ 4 files changed, 65 insertions(+), 36 deletions(-) diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index a8b7b4ec1b..a73ba4df4a 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -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"); } /* diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c index e6b57c648b..4359ef60a8 100644 --- a/src/backend/utils/init/globals.c +++ b/src/backend/utils/init/globals.c @@ -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; diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index f41a01822a..6b5dff9478 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -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; diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index 37db2c7aaf..e7305d67fc 100644 --- a/src/include/utils/elog.h +++ b/src/include/utils/elog.h @@ -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; -- 2.11.0