diff options
| author | Tom Lane | 2001-06-16 22:58:17 +0000 |
|---|---|---|
| committer | Tom Lane | 2001-06-16 22:58:17 +0000 |
| commit | 2917f0a5dd041295bd7e19f6bf868827640d44b0 (patch) | |
| tree | 64cb1e90420a629884642c6df9df7e22cbc87a5d /src/backend/storage | |
| parent | 668db147d5d20291a67749ee0102d70b81a108e7 (diff) | |
Tweak startup sequence so that running out of PROC array slots is
detected sooner in backend startup, and is treated as an expected error
(it gives 'Sorry, too many clients already' now). This allows us not
to have to enforce the MaxBackends limit exactly in the postmaster.
Also, remove ProcRemove() and fold its functionality into ProcKill().
There's no good reason for a backend not to be responsible for removing
its PROC entry, and there are lots of good reasons for the postmaster
not to be touching shared-memory data structures.
Diffstat (limited to 'src/backend/storage')
| -rw-r--r-- | src/backend/storage/ipc/sinval.c | 14 | ||||
| -rw-r--r-- | src/backend/storage/ipc/sinvaladt.c | 14 | ||||
| -rw-r--r-- | src/backend/storage/lmgr/proc.c | 52 |
3 files changed, 35 insertions, 45 deletions
diff --git a/src/backend/storage/ipc/sinval.c b/src/backend/storage/ipc/sinval.c index d60e6198f51..9177a81604b 100644 --- a/src/backend/storage/ipc/sinval.c +++ b/src/backend/storage/ipc/sinval.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.32 2001/06/01 20:07:16 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.33 2001/06/16 22:58:13 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -43,13 +43,15 @@ CreateSharedInvalidationState(int maxBackends) void InitBackendSharedInvalidationState(void) { + int flag; + SpinAcquire(SInvalLock); - if (!SIBackendInit(shmInvalBuffer)) - { - SpinRelease(SInvalLock); - elog(FATAL, "Backend cache invalidation initialization failed"); - } + flag = SIBackendInit(shmInvalBuffer); SpinRelease(SInvalLock); + if (flag < 0) /* unexpected problem */ + elog(FATAL, "Backend cache invalidation initialization failed"); + if (flag == 0) /* expected problem: MaxBackends exceeded */ + elog(FATAL, "Sorry, too many clients already"); } /* diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index 06ba354d94a..63bc037bc9a 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.38 2001/03/22 03:59:45 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.39 2001/06/16 22:58:15 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -79,6 +79,11 @@ SIBufferInit(int maxBackends) * SIBackendInit * Initialize a new backend to operate on the sinval buffer * + * Returns: + * >0 A-OK + * 0 Failed to find a free procState slot (ie, MaxBackends exceeded) + * <0 Some other failure (not currently used) + * * NB: this routine, and all following ones, must be executed with the * SInvalLock spinlock held, since there may be multiple backends trying * to access the buffer. @@ -109,12 +114,7 @@ SIBackendInit(SISeg *segP) } else { - - /* - * elog() with spinlock held is probably not too cool, but - * this condition should never happen anyway. - */ - elog(NOTICE, "SIBackendInit: no free procState slot available"); + /* out of procState slots */ MyBackendId = InvalidBackendId; return 0; } diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index e64d3886aa4..d2a8fe10df8 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.102 2001/05/25 15:45:33 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.103 2001/06/16 22:58:16 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -390,45 +390,16 @@ ProcReleaseLocks(bool isCommit) !isCommit, GetCurrentTransactionId()); } -/* - * ProcRemove - - * called by the postmaster to clean up the global tables after a - * backend exits. This also frees up the proc's wait semaphore. - */ -bool -ProcRemove(int pid) -{ - SHMEM_OFFSET location; - PROC *proc; - - location = ShmemPIDDestroy(pid); - if (location == INVALID_OFFSET) - return FALSE; - proc = (PROC *) MAKE_PTR(location); - - SpinAcquire(ProcStructLock); - - ProcFreeSem(proc->sem.semId, proc->sem.semNum); - - /* Add PROC struct to freelist so space can be recycled in future */ - proc->links.next = ProcGlobal->freeProcs; - ProcGlobal->freeProcs = MAKE_OFFSET(proc); - - SpinRelease(ProcStructLock); - - return TRUE; -} /* * ProcKill() -- Destroy the per-proc data structure for * this process. Release any of its held spin locks. - * - * This is done inside the backend process before it exits. - * ProcRemove, above, will be done by the postmaster afterwards. */ static void ProcKill(void) { + SHMEM_OFFSET location; + Assert(MyProc); /* Release any spinlocks I am holding */ @@ -445,9 +416,26 @@ ProcKill(void) LockReleaseAll(USER_LOCKMETHOD, MyProc, true, InvalidTransactionId); #endif + /* Remove my PROC struct from the shmem hash table */ + location = ShmemPIDDestroy(MyProcPid); + Assert(location != INVALID_OFFSET); + Assert(MyProc == (PROC *) MAKE_PTR(location)); + + SpinAcquire(ProcStructLock); + + /* Free up my wait semaphore */ + ProcFreeSem(MyProc->sem.semId, MyProc->sem.semNum); + + /* Add PROC struct to freelist so space can be recycled in future */ + MyProc->links.next = ProcGlobal->freeProcs; + ProcGlobal->freeProcs = MAKE_OFFSET(MyProc); + + SpinRelease(ProcStructLock); + MyProc = NULL; } + /* * ProcQueue package: routines for putting processes to sleep * and waking them up |
