1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-10 17:42:29 +03:00

Cause ShutdownPostgres to do a normal transaction abort during backend

exit, instead of trying to take shortcuts.  Introduce some additional
shutdown callback routines to eliminate kluges like having ProcKill
be responsible for shutting down the buffer manager.  Ensure that the
order of operations during shutdown is predictable and what you would
expect given the module layering.
This commit is contained in:
Tom Lane
2005-08-08 03:12:16 +00:00
parent 89439b8c4f
commit 7117cd3a77
11 changed files with 119 additions and 100 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/buffer/buf_init.c,v 1.73 2005/05/19 21:35:46 tgl Exp $
* $PostgreSQL: pgsql/src/backend/storage/buffer/buf_init.c,v 1.74 2005/08/08 03:11:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -149,6 +149,7 @@ InitBufferPool(void)
* NB: this is called before InitProcess(), so we do not have a PGPROC and
* cannot do LWLockAcquire; hence we can't actually access stuff in
* shared memory yet. We are only initializing local data here.
* (See also InitBufferPoolBackend, over in bufmgr.c.)
*/
void
InitBufferPoolAccess(void)

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.190 2005/08/02 20:52:08 tgl Exp $
* $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.191 2005/08/08 03:11:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -45,6 +45,7 @@
#include "storage/buf_internals.h"
#include "storage/bufmgr.h"
#include "storage/bufpage.h"
#include "storage/ipc.h"
#include "storage/proc.h"
#include "storage/smgr.h"
#include "utils/relcache.h"
@@ -93,6 +94,7 @@ static void buffer_write_error_callback(void *arg);
static BufferDesc *BufferAlloc(Relation reln, BlockNumber blockNum,
bool *foundPtr);
static void FlushBuffer(BufferDesc *buf, SMgrRelation reln);
static void AtProcExit_Buffers(int code, Datum arg);
static void write_buffer(Buffer buffer, bool unpin);
@@ -1080,10 +1082,25 @@ AtEOXact_Buffers(bool isCommit)
}
/*
* Ensure we have released all shared-buffer locks and pins during backend exit
* InitBufferPoolBackend --- second-stage initialization of a new backend
*
* This is called after we have acquired a PGPROC and so can safely get
* LWLocks. We don't currently need to do anything at this stage ...
* except register a shmem-exit callback. AtProcExit_Buffers needs LWLock
* access, and thereby has to be called at the corresponding phase of
* backend shutdown.
*/
void
AtProcExit_Buffers(void)
InitBufferPoolBackend(void)
{
on_shmem_exit(AtProcExit_Buffers, 0);
}
/*
* Ensure we have released all shared-buffer locks and pins during backend exit
*/
static void
AtProcExit_Buffers(int code, Datum arg)
{
int i;
@@ -1105,6 +1122,9 @@ AtProcExit_Buffers(void)
Assert(PrivateRefCount[i] == 0);
}
}
/* localbuf.c needs a chance too */
AtProcExit_LocalBuffers();
}
/*

View File

@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.119 2005/08/07 18:47:19 tgl Exp $
* $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.120 2005/08/08 03:11:49 tgl Exp $
*
* NOTES:
*
@@ -296,6 +296,33 @@ pg_fdatasync(int fd)
return 0;
}
/*
* InitFileAccess --- initialize this module during backend startup
*
* This is called during either normal or standalone backend start.
* It is *not* called in the postmaster.
*/
void
InitFileAccess(void)
{
Assert(SizeVfdCache == 0); /* call me only once */
/* initialize cache header entry */
VfdCache = (Vfd *) malloc(sizeof(Vfd));
if (VfdCache == NULL)
ereport(FATAL,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory")));
MemSet((char *) &(VfdCache[0]), 0, sizeof(Vfd));
VfdCache->fd = VFD_CLOSED;
SizeVfdCache = 1;
/* register proc-exit hook to ensure temp files are dropped at exit */
on_proc_exit(AtProcExit_Files, 0);
}
/*
* count_usable_fds --- count how many FDs the system will let us open,
* and estimate how many are already open.
@@ -622,25 +649,7 @@ AllocateVfd(void)
DO_DB(elog(LOG, "AllocateVfd. Size %d", SizeVfdCache));
if (SizeVfdCache == 0)
{
/* initialize header entry first time through */
VfdCache = (Vfd *) malloc(sizeof(Vfd));
if (VfdCache == NULL)
ereport(FATAL,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory")));
MemSet((char *) &(VfdCache[0]), 0, sizeof(Vfd));
VfdCache->fd = VFD_CLOSED;
SizeVfdCache = 1;
/*
* register proc-exit call to ensure temp files are dropped at
* exit
*/
on_proc_exit(AtProcExit_Files, 0);
}
Assert(SizeVfdCache > 0); /* InitFileAccess not called? */
if (VfdCache[0].nextFree == 0)
{

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.161 2005/07/31 17:19:19 tgl Exp $
* $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.162 2005/08/08 03:11:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -144,7 +144,7 @@ InitProcGlobal(void)
ShmemInitStruct("Proc Header", sizeof(PROC_HDR), &foundProcGlobal);
/*
* Create or attach to the PGPROC structures for dummy (checkpoint)
* Create or attach to the PGPROC structures for dummy (bgwriter)
* processes, too. These do not get linked into the freeProcs list.
*/
DummyProcs = (PGPROC *)
@@ -289,9 +289,10 @@ InitProcess(void)
/*
* InitDummyProcess -- create a dummy per-process data structure
*
* This is called by checkpoint processes so that they will have a MyProc
* value that's real enough to let them wait for LWLocks. The PGPROC and
* sema that are assigned are the extra ones created during InitProcGlobal.
* This is called by bgwriter and similar processes so that they will have a
* MyProc value that's real enough to let them wait for LWLocks. The PGPROC
* and sema that are assigned are the extra ones created during
* InitProcGlobal.
*
* Dummy processes are presently not expected to wait for real (lockmgr)
* locks, nor to participate in sinval messaging.
@@ -485,27 +486,12 @@ ProcKill(int code, Datum arg)
Assert(MyProc != NULL);
/* Release any LW locks I am holding */
LWLockReleaseAll();
/*
* Make real sure we release any buffer locks and pins we might be
* holding, too. It is pretty ugly to do this here and not in a
* shutdown callback registered by the bufmgr ... but we must do this
* *after* LWLockReleaseAll and *before* zapping MyProc.
* Release any LW locks I am holding. There really shouldn't be any,
* but it's cheap to check again before we cut the knees off the LWLock
* facility by releasing our PGPROC ...
*/
AtProcExit_Buffers();
/* Get off any wait queue I might be on */
LockWaitCancel();
/* Remove from the standard lock table */
LockReleaseAll(DEFAULT_LOCKMETHOD, true);
#ifdef USER_LOCKS
/* Remove from the user lock table */
LockReleaseAll(USER_LOCKMETHOD, true);
#endif
LWLockReleaseAll();
/* Remove our PGPROC from the PGPROC array in shared memory */
ProcArrayRemove(MyProc);
@@ -523,7 +509,7 @@ ProcKill(int code, Datum arg)
}
/*
* DummyProcKill() -- Cut-down version of ProcKill for dummy (checkpoint)
* DummyProcKill() -- Cut-down version of ProcKill for dummy (bgwriter)
* processes. The PGPROC and sema are not released, only marked
* as not-in-use.
*/
@@ -539,14 +525,9 @@ DummyProcKill(int code, Datum arg)
Assert(MyProc == dummyproc);
/* Release any LW locks I am holding */
/* Release any LW locks I am holding (see notes above) */
LWLockReleaseAll();
/* Release buffer locks and pins, too */
AtProcExit_Buffers();
/* I can't be on regular lock queues, so needn't check */
/* Mark dummy proc no longer in use */
MyProc->pid = 0;

View File

@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/smgr/smgr.c,v 1.91 2005/06/20 18:37:01 tgl Exp $
* $PostgreSQL: pgsql/src/backend/storage/smgr/smgr.c,v 1.92 2005/08/08 03:12:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -136,11 +136,12 @@ static void smgr_internal_unlink(RelFileNode rnode, int which,
/*
* smgrinit(), smgrshutdown() -- Initialize or shut down all storage
* smgrinit(), smgrshutdown() -- Initialize or shut down storage
* managers.
*
* Note: in the normal multiprocess scenario with a postmaster, these are
* called at postmaster start and stop, not per-backend.
* Note: smgrinit is called during backend startup (normal or standalone
* case), *not* during postmaster start. Therefore, any resources created
* here or destroyed in smgrshutdown are backend-local.
*/
void
smgrinit(void)
@@ -162,6 +163,9 @@ smgrinit(void)
on_proc_exit(smgrshutdown, 0);
}
/*
* on_proc_exit hook for smgr cleanup during backend shutdown
*/
static void
smgrshutdown(int code, Datum arg)
{