From a626b78c8957f50ae6345015b249e996d9aab55d Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 18 Dec 2000 00:44:50 +0000 Subject: [PATCH] Clean up backend-exit-time cleanup behavior. Use on_shmem_exit callbacks to ensure that we have released buffer refcounts and so forth, rather than putting ad-hoc operations before (some of the calls to) proc_exit. Add commentary to discourage future hackers from repeating that mistake. --- src/backend/access/transam/xact.c | 30 +++++----- src/backend/access/transam/xlog.c | 12 ++-- src/backend/commands/trigger.c | 6 +- src/backend/libpq/pqcomm.c | 8 ++- src/backend/storage/buffer/buf_init.c | 56 +++++++++++++++-- src/backend/storage/lmgr/proc.c | 13 ++-- src/backend/tcop/postgres.c | 100 +++++++++++++++++-------------- src/backend/utils/error/elog.c | 26 ++++---- src/backend/utils/init/postinit.c | 109 ++++++++++++++++++++++++++-------- src/include/access/xlog.h | 4 +- src/include/commands/trigger.h | 4 +- src/include/libpq/libpq.h | 3 +- src/include/storage/bufmgr.h | 3 +- src/include/utils/elog.h | 20 +++---- 14 files changed, 255 insertions(+), 139 deletions(-) diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 6cd089fd95..c8c9e680f5 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.88 2000/12/07 10:03:46 inoue Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.89 2000/12/18 00:44:45 tgl Exp $ * * NOTES * Transaction aborts can now occur two ways: @@ -1095,6 +1095,15 @@ AbortTransaction(void) MyProc->xmin = InvalidTransactionId; } + /* + * Release any spinlocks or buffer context locks we might be holding + * as quickly as possible. (Real locks, however, must be held till + * we finish aborting.) Releasing spinlocks is critical since we + * might try to grab them again while cleaning up! + */ + ProcReleaseSpins(NULL); + UnlockBuffers(); + /* ---------------- * check the current transaction state * ---------------- @@ -1105,18 +1114,6 @@ AbortTransaction(void) if (s->state != TRANS_INPROGRESS) elog(NOTICE, "AbortTransaction and not in in-progress state"); - /* - * Reset user id which might have been changed transiently - */ - SetUserId(GetSessionUserId()); - - /* ---------------- - * Tell the trigger manager that this transaction is about to be - * aborted. - * ---------------- - */ - DeferredTriggerAbortXact(); - /* ---------------- * set the current transaction state information * appropriately during the abort processing @@ -1124,12 +1121,17 @@ AbortTransaction(void) */ s->state = TRANS_ABORT; + /* + * Reset user id which might have been changed transiently + */ + SetUserId(GetSessionUserId()); + /* ---------------- * do abort processing * ---------------- */ + DeferredTriggerAbortXact(); lo_commit(false); /* 'false' means it's abort */ - UnlockBuffers(); AtAbort_Notify(); CloseSequences(); AtEOXact_portals(); diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 3b2c5461dc..ba85f4b60d 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.42 2000/12/11 19:27:42 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.43 2000/12/18 00:44:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -40,7 +40,7 @@ int XLOGbuffers = 8; XLogRecPtr MyLastRecPtr = {0, 0}; -uint32 StopIfError = 0; +uint32 CritSectionCount = 0; bool InRecovery = false; StartUpID ThisStartUpID = 0; @@ -1531,7 +1531,7 @@ StartupXLOG() char buffer[MAXLOGRECSZ + SizeOfXLogRecord]; elog(LOG, "starting up"); - StopIfError++; + CritSectionCount++; XLogCtl->xlblocks = (XLogRecPtr *) (((char *) XLogCtl) + sizeof(XLogCtlData)); XLogCtl->pages = ((char *) XLogCtl->xlblocks + sizeof(XLogRecPtr) * XLOGbuffers); @@ -1748,7 +1748,7 @@ StartupXLOG() XLogCtl->ThisStartUpID = ThisStartUpID; elog(LOG, "database system is in production state"); - StopIfError--; + CritSectionCount--; return; } @@ -1771,10 +1771,10 @@ ShutdownXLOG() { elog(LOG, "shutting down"); - StopIfError++; + CritSectionCount++; CreateDummyCaches(); CreateCheckPoint(true); - StopIfError--; + CritSectionCount--; elog(LOG, "database system is shut down"); } diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index cc31a0eb48..d5946ebd3e 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.81 2000/11/20 20:36:47 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.82 2000/12/18 00:44:46 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1432,7 +1432,7 @@ deferredTriggerInvokeEvents(bool immediate_only) * transactions. * ---------- */ -int +void DeferredTriggerInit(void) { deftrig_gcxt = AllocSetContextCreate(TopMemoryContext, @@ -1440,8 +1440,6 @@ DeferredTriggerInit(void) ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); - - return 0; } diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c index 35d6802a5a..0d2548c96a 100644 --- a/src/backend/libpq/pqcomm.c +++ b/src/backend/libpq/pqcomm.c @@ -29,7 +29,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pqcomm.c,v 1.114 2000/11/29 20:59:51 tgl Exp $ + * $Id: pqcomm.c,v 1.115 2000/12/18 00:44:46 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -85,6 +85,9 @@ #endif +static void pq_close(void); + + /* * Configuration options */ @@ -122,6 +125,7 @@ pq_init(void) { PqSendPointer = PqRecvPointer = PqRecvLength = 0; DoingCopyOut = false; + on_proc_exit(pq_close, 0); } @@ -132,7 +136,7 @@ pq_init(void) * don't crash during exit... * -------------------------------- */ -void +static void pq_close(void) { if (MyProcPort != NULL) diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index 19b71933d7..54b9d02e16 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.39 2000/11/30 01:39:07 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.40 2000/12/18 00:44:46 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -36,6 +36,9 @@ #include "utils/hsearch.h" #include "utils/memutils.h" + +static void ShutdownBufferPoolAccess(void); + /* * if BMTRACE is defined, we trace the last 200 buffer allocations and * deallocations in a circular buffer in shared memory. @@ -73,7 +76,7 @@ bool *BufferDirtiedByMe; /* T if buf has been dirtied in cur xact */ * Two important notes. First, the buffer has to be * available for lookup BEFORE an IO begins. Otherwise * a second process trying to read the buffer will - * allocate its own copy and the buffeer pool will + * allocate its own copy and the buffer pool will * become inconsistent. * * Buffer Replacement: @@ -126,10 +129,10 @@ long int LocalBufferFlushCount; /* - * Initialize module: called once during shared-memory initialization + * Initialize shared buffer pool * - * should calculate size of pool dynamically based on the - * amount of available memory. + * This is called once during shared-memory initialization (either in the + * postmaster, or in a standalone backend). */ void InitBufferPool(void) @@ -144,6 +147,10 @@ InitBufferPool(void) Lookup_List_Descriptor = Data_Descriptors + 1; Num_Descriptors = Data_Descriptors + 1; + /* + * It's probably not really necessary to grab the lock --- if there's + * anyone else attached to the shmem at this point, we've got problems. + */ SpinAcquire(BufMgrLock); #ifdef BMTRACE @@ -203,12 +210,28 @@ InitBufferPool(void) BufferDescriptors[Data_Descriptors - 1].freeNext = 0; } - /* Init the rest of the module */ + /* Init other shared buffer-management stuff */ InitBufTable(); InitFreeList(!foundDescs); SpinRelease(BufMgrLock); +} + +/* + * Initialize access to shared buffer pool + * + * This is called during backend startup (whether standalone or under the + * postmaster). It sets up for this backend's access to the already-existing + * buffer pool. + */ +void +InitBufferPoolAccess(void) +{ + int i; + /* + * Allocate and zero local arrays of per-buffer info. + */ BufferBlockPointers = (Block *) calloc(NBuffers, sizeof(Block)); PrivateRefCount = (long *) calloc(NBuffers, sizeof(long)); BufferLocks = (bits8 *) calloc(NBuffers, sizeof(bits8)); @@ -224,6 +247,27 @@ InitBufferPool(void) { BufferBlockPointers[i] = (Block) MAKE_PTR(BufferDescriptors[i].data); } + + /* + * Now that buffer access is initialized, set up a callback to shut it + * down again at backend exit. + */ + on_shmem_exit(ShutdownBufferPoolAccess, 0); +} + +/* + * Shut down buffer manager at backend exit. + * + * This is needed mainly to ensure that we don't leave any buffer reference + * counts set during an error exit. + */ +static void +ShutdownBufferPoolAccess(void) +{ + /* Release any buffer context locks we are holding */ + UnlockBuffers(); + /* Release any buffer reference counts we are holding */ + ResetBufferPool(false); } /* ----------------------------------------------------- diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 29502c3016..a95432e0f8 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.86 2000/12/11 16:35:59 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.87 2000/12/18 00:44:47 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -29,7 +29,8 @@ * * Interface (b): * - * ProcReleaseLocks -- frees the locks associated with this process, + * ProcReleaseLocks -- frees the locks associated with current transaction + * * ProcKill -- destroys the shared memory state (and locks) * associated with the process. * @@ -47,7 +48,7 @@ * This is so that we can support more backends. (system-wide semaphore * sets run out pretty fast.) -ay 4/95 * - * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.86 2000/12/11 16:35:59 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.87 2000/12/18 00:44:47 tgl Exp $ */ #include "postgres.h" @@ -332,7 +333,7 @@ GetOffWaitqueue(PROC *proc) } /* - * ProcReleaseLocks() -- release all locks associated with this process + * ProcReleaseLocks() -- release all locks associated with current transaction * */ void @@ -340,7 +341,7 @@ ProcReleaseLocks() { if (!MyProc) return; - LockReleaseAll(1, &MyProc->lockQueue); + LockReleaseAll(DEFAULT_LOCKMETHOD, &MyProc->lockQueue); GetOffWaitqueue(MyProc); } @@ -423,8 +424,6 @@ ProcKill(int exitStatus, Datum pid) * ---------------- */ GetOffWaitqueue(proc); - - return; } /* diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 3d74d187ff..706b5d1fbf 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.194 2000/12/03 10:27:27 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.195 2000/12/18 00:44:47 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -61,7 +61,6 @@ #include "utils/guc.h" #include "utils/memutils.h" #include "utils/ps_status.h" -#include "utils/temprel.h" #ifdef MULTIBYTE #include "mb/pg_wchar.h" #endif @@ -95,7 +94,7 @@ DLLIMPORT sigjmp_buf Warn_restart; bool Warn_restart_ready = false; bool InError = false; -bool ExitAfterAbort = false; +bool ProcDiePending = false; static bool EchoQuery = false; /* default don't echo */ char pg_pathname[MAXPGPATH]; @@ -921,7 +920,8 @@ finish_xact_command(void) void handle_warn(SIGNAL_ARGS) { - if (StopIfError) + /* Don't joggle the elbow of a critical section */ + if (CritSectionCount > 0) { QueryCancel = true; return; @@ -958,13 +958,15 @@ die(SIGNAL_ARGS) { PG_SETMASK(&BlockSig); - ExitAfterAbort = true; - if (StopIfError) + /* Don't joggle the elbow of a critical section */ + if (CritSectionCount > 0) { QueryCancel = true; + ProcDiePending = true; return; } - if (InError) /* If ERROR/FATAL is in progress... */ + /* Don't joggle the elbow of proc_exit, either */ + if (proc_exit_inprogress) return; elog(FATAL, "The system is shutting down"); } @@ -1096,6 +1098,8 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha MemoryContextInit(); } + SetProcessingMode(InitProcessing); + /* * Set default values for command-line options. */ @@ -1109,8 +1113,6 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha } StatFp = stderr; - SetProcessingMode(InitProcessing); - /* Check for PGDATESTYLE environment variable */ set_default_datestyle(); @@ -1428,11 +1430,16 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha break; } - + /* + * Post-processing for command line options. + * + * XXX It'd be nice if libpq were already running here, so we could do + * elog(NOTICE) instead of just writing on stderr... + */ if (Show_query_stats && (Show_parser_stats || Show_planner_stats || Show_executor_stats)) { - elog(NOTICE, "Query statistics are disabled because parser, planner, or executor statistics are on."); + fprintf(stderr, "Query statistics are disabled because parser, planner, or executor statistics are on.\n"); Show_query_stats = false; } @@ -1528,7 +1535,13 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha XLOGPathInit(); BaseInit(); + + /* + * Start up xlog for standalone backend, and register to have it + * closed down at exit. + */ StartupXLOG(); + on_shmem_exit(ShutdownXLOG, 0); } /* @@ -1602,20 +1615,17 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha remote_host, username, DBName); /* - * general initialization + * General initialization. + * + * NOTE: if you are tempted to add code in this vicinity, consider + * putting it inside InitPostgres() instead. In particular, anything + * that involves database access should be there, not here. */ if (DebugLvl > 1) elog(DEBUG, "InitPostgres"); InitPostgres(DBName, username); -#ifdef MULTIBYTE - /* set default client encoding */ - if (DebugLvl > 1) - elog(DEBUG, "set_default_client_encoding"); - set_default_client_encoding(); -#endif - - on_shmem_exit(remove_all_temp_relations, 0); + SetProcessingMode(NormalProcessing); /* * Send this backend's cancellation info to the frontend. @@ -1636,18 +1646,10 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.194 $ $Date: 2000/12/03 10:27:27 $\n"); + puts("$Revision: 1.195 $ $Date: 2000/12/18 00:44:47 $\n"); } /* - * Initialize the deferred trigger manager - */ - if (DeferredTriggerInit() != 0) - goto normalexit; - - SetProcessingMode(NormalProcessing); - - /* * Create the memory context we will use in the main loop. * * QueryContext is reset once per iteration of the main loop, @@ -1671,6 +1673,10 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha if (sigsetjmp(Warn_restart, 1) != 0) { /* + * NOTE: if you are tempted to add more code in this if-block, + * consider the probability that it should be in AbortTransaction() + * instead. + * * Make sure we are in a valid memory context during recovery. * * We use ErrorContext in hopes that it will have some free space @@ -1678,19 +1684,22 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha */ MemoryContextSwitchTo(ErrorContext); + /* Do the recovery */ if (DebugLvl >= 1) elog(DEBUG, "AbortCurrentTransaction"); AbortCurrentTransaction(); - if (ExitAfterAbort) - goto errorexit; - /* - * If we recovered successfully, return to normal top-level context - * and clear ErrorContext for next time. + * Now return to normal top-level context and clear ErrorContext + * for next time. */ MemoryContextSwitchTo(TopMemoryContext); MemoryContextResetAndDeleteChildren(ErrorContext); + + /* + * Clear flag to indicate that we got out of error recovery mode + * successfully. (Flag was set in elog.c before longjmp().) + */ InError = false; } @@ -1775,7 +1784,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha if (HandleFunctionRequest() == EOF) { /* lost frontend connection during F message input */ - goto normalexit; + proc_exit(0); } /* commit the function-invocation transaction */ @@ -1830,7 +1839,14 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha */ case 'X': case EOF: - goto normalexit; + /* + * NOTE: if you are tempted to add more code here, DON'T! + * Whatever you had in mind to do should be set up as + * an on_proc_exit or on_shmem_exit callback, instead. + * Otherwise it will fail to be called during other + * backend-shutdown scenarios. + */ + proc_exit(0); default: elog(ERROR, "unknown frontend message was received"); @@ -1845,16 +1861,8 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha #endif } /* end of input-reading loop */ -normalexit: - ExitAfterAbort = true; /* ensure we will exit if elog during abort */ - AbortOutOfAnyTransaction(); - if (!IsUnderPostmaster) - ShutdownXLOG(); - -errorexit: - pq_close(); - ProcReleaseLocks(); /* Just to be sure... */ - proc_exit(0); + /* can't get here because the above loop never exits */ + Assert(false); return 1; /* keep compiler quiet */ } diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index cb56f33c83..6a9ef98f97 100644 --- a/src/backend/utils/error/elog.c +++ b/src/backend/utils/error/elog.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.73 2000/12/06 17:25:46 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.74 2000/12/18 00:44:47 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -159,7 +159,7 @@ elog(int lev, const char *fmt, ...) /* this is probably redundant... */ if (IsInitProcessingMode()) lev = FATAL; - if (StopIfError) + if (CritSectionCount > 0) lev = STOP; } @@ -445,21 +445,26 @@ elog(int lev, const char *fmt, ...) { /* + * For a FATAL error, we let proc_exit clean up and exit. + * * If we have not yet entered the main backend loop (ie, we are in - * the postmaster or in backend startup), then go directly to + * the postmaster or in backend startup), we also go directly to * proc_exit. The same is true if anyone tries to report an error * after proc_exit has begun to run. (It's proc_exit's * responsibility to see that this doesn't turn into infinite * recursion!) But in the latter case, we exit with nonzero exit * code to indicate that something's pretty wrong. */ - if (proc_exit_inprogress || !Warn_restart_ready) + if (lev == FATAL || !Warn_restart_ready || proc_exit_inprogress) { + /* + * fflush here is just to improve the odds that we get to see + * the error message, in case things are so hosed that proc_exit + * crashes. Any other code you might be tempted to add here + * should probably be in an on_proc_exit callback instead. + */ fflush(stdout); fflush(stderr); - ProcReleaseSpins(NULL); /* get rid of spinlocks we hold */ - ProcReleaseLocks(); /* get rid of real locks we hold */ - /* XXX shouldn't proc_exit be doing the above?? */ proc_exit((int) proc_exit_inprogress); } @@ -471,13 +476,8 @@ elog(int lev, const char *fmt, ...) InError = true; /* - * Otherwise we can return to the main loop in postgres.c. In the - * FATAL case, postgres.c will call proc_exit, but not till after - * completing a standard transaction-abort sequence. + * Otherwise we can return to the main loop in postgres.c. */ - ProcReleaseSpins(NULL); /* get rid of spinlocks we hold */ - if (lev == FATAL) - ExitAfterAbort = true; siglongjmp(Warn_restart, 1); } diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index f213e561c1..c8bd8a0d26 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.75 2000/12/14 23:51:35 wieck Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.76 2000/12/18 00:44:48 tgl Exp $ * * *------------------------------------------------------------------------- @@ -28,6 +28,7 @@ #include "access/heapam.h" #include "catalog/catname.h" #include "catalog/pg_database.h" +#include "commands/trigger.h" #include "miscadmin.h" #include "storage/backendid.h" #include "storage/proc.h" @@ -37,6 +38,7 @@ #include "utils/portal.h" #include "utils/relcache.h" #include "utils/syscache.h" +#include "utils/temprel.h" #ifdef MULTIBYTE #include "mb/pg_wchar.h" @@ -44,6 +46,9 @@ static void ReverifyMyDatabase(const char *name); static void InitCommunication(void); +static void ShutdownPostgres(void); + +int lockingOff = 0; /* backend -L switch */ /*** InitPostgres support ***/ @@ -115,12 +120,8 @@ ReverifyMyDatabase(const char *name) */ dbform = (Form_pg_database) GETSTRUCT(tup); if (! dbform->datallowconn) - { - heap_endscan(pgdbscan); - heap_close(pgdbrel, AccessShareLock); elog(FATAL, "Database \"%s\" is not currently accepting connections", name); - } /* * OK, we're golden. Only other to-do item is to save the MULTIBYTE @@ -163,6 +164,28 @@ InitCommunication(void) } +/* + * Early initialization of a backend (either standalone or under postmaster). + * This happens even before InitPostgres. + */ +void +BaseInit(void) +{ + /* + * Attach to shared memory and semaphores, and initialize our + * input/output/debugging file descriptors. + */ + InitCommunication(); + DebugFileOpen(); + + /* Do local initialization of storage and buffer managers */ + smgrinit(); + InitBufferPoolAccess(); + InitLocalBuffer(); + + EnablePortalManager(); /* memory for portal/transaction stuff */ +} + /* -------------------------------- * InitPostgres @@ -172,16 +195,13 @@ InitCommunication(void) * Be very careful with the order of calls in the InitPostgres function. * -------------------------------- */ -int lockingOff = 0; /* backend -L switch */ - -/* - */ void InitPostgres(const char *dbname, const char *username) { bool bootstrap = IsBootstrapProcessingMode(); SetDatabaseName(dbname); + /* ---------------- * initialize the database id used for system caches and lock tables * ---------------- @@ -299,6 +319,12 @@ InitPostgres(const char *dbname, const char *username) */ InitCatalogCache(); + /* + * Initialize the deferred trigger manager --- must happen before + * first transaction start. + */ + DeferredTriggerInit(); + /* start a new transaction here before access to db */ if (!bootstrap) StartTransactionCommand(); @@ -322,27 +348,62 @@ InitPostgres(const char *dbname, const char *username) /* * Unless we are bootstrapping, double-check that InitMyDatabaseInfo() - * got a correct result. We can't do this until essentially all the - * infrastructure is up, so just do it at the end. + * got a correct result. We can't do this until all the database-access + * infrastructure is up. */ if (!bootstrap) ReverifyMyDatabase(dbname); -} -void -BaseInit(void) -{ +#ifdef MULTIBYTE + /* set default client encoding --- uses info from ReverifyMyDatabase */ + set_default_client_encoding(); +#endif + /* - * Attach to shared memory and semaphores, and initialize our - * input/output/debugging file descriptors. + * Set up process-exit callbacks to remove temp relations and then + * do pre-shutdown cleanup. This should be last because we want + * shmem_exit to call these routines before the exit callbacks that + * are registered by buffer manager, lock manager, etc. We need + * to run this code before we close down database access! */ - InitCommunication(); - DebugFileOpen(); - - smgrinit(); + on_shmem_exit(ShutdownPostgres, 0); + /* because callbacks are called in reverse order, this gets done first: */ + on_shmem_exit(remove_all_temp_relations, 0); - EnablePortalManager(); /* memory for portal/transaction stuff */ + /* close the transaction we started above */ + if (!bootstrap) + CommitTransactionCommand(); +} - /* initialize the local buffer manager */ - InitLocalBuffer(); +/* + * Backend-shutdown callback. Do cleanup that we want to be sure happens + * before all the supporting modules begin to nail their doors shut via + * their own callbacks. Note that because this has to be registered very + * late in startup, it will not get called if we suffer a failure *during* + * startup. + * + * User-level cleanup, such as temp-relation removal and UNLISTEN, happens + * via separate callbacks that execute before this one. We don't combine the + * callbacks because we still want this one to happen if the user-level + * cleanup fails. + */ +static void +ShutdownPostgres(void) +{ + /* + * These operations are really just a minimal subset of AbortTransaction(). + * We don't want to do any inessential cleanup, since that just raises + * the odds of failure --- but there's some stuff we need to do. + * + * Release any spinlocks that we may hold. This is a kluge to improve + * the odds that we won't get into a self-made stuck spinlock scenario + * while trying to shut down. + */ + ProcReleaseSpins(NULL); + /* + * In case a transaction is open, delete any files it created. This + * has to happen before bufmgr shutdown, so having smgr register a + * callback for it wouldn't work. + */ + smgrDoPendingDeletes(false); /* delete as though aborting xact */ } diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h index 269315dc78..1c10501fb7 100644 --- a/src/include/access/xlog.h +++ b/src/include/access/xlog.h @@ -3,7 +3,7 @@ * * PostgreSQL transaction log manager * - * $Header: /cvsroot/pgsql/src/include/access/xlog.h,v 1.13 2000/12/03 10:27:28 vadim Exp $ + * $Header: /cvsroot/pgsql/src/include/access/xlog.h,v 1.14 2000/12/18 00:44:48 tgl Exp $ */ #ifndef XLOG_H #define XLOG_H @@ -88,7 +88,7 @@ typedef XLogPageHeaderData *XLogPageHeader; extern StartUpID ThisStartUpID; /* current SUI */ extern bool InRecovery; extern XLogRecPtr MyLastRecPtr; -extern uint32 StopIfError; +extern uint32 CritSectionCount; typedef struct RmgrData { diff --git a/src/include/commands/trigger.h b/src/include/commands/trigger.h index 22dac3f5fe..c9fbcae54a 100644 --- a/src/include/commands/trigger.h +++ b/src/include/commands/trigger.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: trigger.h,v 1.21 2000/06/08 22:37:42 momjian Exp $ + * $Id: trigger.h,v 1.22 2000/12/18 00:44:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -129,7 +129,7 @@ typedef struct DeferredTriggerEventData typedef struct DeferredTriggerEventData *DeferredTriggerEvent; -extern int DeferredTriggerInit(void); +extern void DeferredTriggerInit(void); extern void DeferredTriggerBeginXact(void); extern void DeferredTriggerEndQuery(void); extern void DeferredTriggerEndXact(void); diff --git a/src/include/libpq/libpq.h b/src/include/libpq/libpq.h index c86862317c..a8deb15eee 100644 --- a/src/include/libpq/libpq.h +++ b/src/include/libpq/libpq.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: libpq.h,v 1.41 2000/11/14 01:15:04 momjian Exp $ + * $Id: libpq.h,v 1.42 2000/12/18 00:44:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -60,7 +60,6 @@ extern int StreamServerPort(int family, char *hostName, extern int StreamConnection(int server_fd, Port *port); extern void StreamClose(int sock); extern void pq_init(void); -extern void pq_close(void); extern int pq_getbytes(char *s, size_t len); extern int pq_getstring(StringInfo s); extern int pq_peekbyte(void); diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h index 27bcc090ed..7f1906441a 100644 --- a/src/include/storage/bufmgr.h +++ b/src/include/storage/bufmgr.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: bufmgr.h,v 1.46 2000/11/30 08:46:26 vadim Exp $ + * $Id: bufmgr.h,v 1.47 2000/12/18 00:44:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -168,6 +168,7 @@ extern Buffer ReleaseAndReadBuffer(Buffer buffer, Relation relation, extern int FlushBuffer(Buffer buffer, bool sync, bool release); extern void InitBufferPool(void); +extern void InitBufferPoolAccess(void); extern void PrintBufferUsage(FILE *statfp); extern void ResetBufferUsage(void); extern void ResetBufferPool(bool isCommit); diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index acb8204973..37db2c7aaf 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.20 2000/12/06 17:25:45 tgl Exp $ + * $Id: elog.h,v 1.21 2000/12/18 00:44:50 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -28,24 +28,24 @@ extern int Use_syslog; #endif /* - * If StopIfError > 0 signal handlers mustn't do + * If CritSectionCount > 0, signal handlers mustn't do * elog(ERROR|FATAL), instead remember what action is - * required with QueryCancel & ExitAfterAbort. + * required with QueryCancel & ProcDiePending. */ -extern uint32 StopIfError; /* duplicates access/xlog.h */ +extern uint32 CritSectionCount; /* duplicates access/xlog.h */ extern bool QueryCancel; /* duplicates miscadmin.h */ -extern bool ExitAfterAbort; +extern bool ProcDiePending; -#define START_CRIT_CODE (StopIfError++) +#define START_CRIT_CODE (CritSectionCount++) #define END_CRIT_CODE \ do { \ - if (!StopIfError) \ + if (CritSectionCount == 0) \ elog(STOP, "Not in critical section"); \ - StopIfError--; \ - if (!StopIfError && QueryCancel) \ + CritSectionCount--; \ + if (CritSectionCount == 0 && QueryCancel) \ { \ - if (ExitAfterAbort) \ + if (ProcDiePending) \ elog(FATAL, "The system is shutting down"); \ else \ elog(ERROR, "Query was cancelled."); \ -- 2.11.0