mirror of
https://github.com/postgres/postgres.git
synced 2025-07-15 19:21:59 +03:00
Change the autovacuum launcher to use WaitLatch instead of a poll loop.
In pursuit of this (and with the expectation that WaitLatch will be needed in more places), convert the latch field that was already added to PGPROC for sync rep into a generic latch that is activated for all PGPROC-owning processes, and change many of the standard backend signal handlers to set that latch when a signal happens. This will allow WaitLatch callers to be wakened properly by these signals. In passing, fix a whole bunch of signal handlers that had been hacked to do things that might change errno, without adding the necessary save/restore logic for errno. Also make some minor fixes in unix_latch.c, and clean up bizarre and unsafe scheme for disowning the process's latch. Much of this has to be back-patched into 9.1. Peter Geoghegan, with additional work by Tom
This commit is contained in:
@ -196,9 +196,11 @@ InitProcGlobal(void)
|
||||
for (i = 0; i < TotalProcs; i++)
|
||||
{
|
||||
/* Common initialization for all PGPROCs, regardless of type. */
|
||||
|
||||
/* Set up per-PGPROC semaphore, latch, and backendLock */
|
||||
PGSemaphoreCreate(&(procs[i].sem));
|
||||
InitSharedLatch(&(procs[i].procLatch));
|
||||
procs[i].backendLock = LWLockAssign();
|
||||
InitSharedLatch(&procs[i].waitLatch);
|
||||
|
||||
/*
|
||||
* Newly created PGPROCs for normal backends or for autovacuum must
|
||||
@ -300,8 +302,8 @@ InitProcess(void)
|
||||
MarkPostmasterChildActive();
|
||||
|
||||
/*
|
||||
* Initialize all fields of MyProc, except for the semaphore which was
|
||||
* prepared for us by InitProcGlobal.
|
||||
* Initialize all fields of MyProc, except for the semaphore and latch,
|
||||
* which were prepared for us by InitProcGlobal.
|
||||
*/
|
||||
SHMQueueElemInit(&(MyProc->links));
|
||||
MyProc->waitStatus = STATUS_OK;
|
||||
@ -327,12 +329,17 @@ InitProcess(void)
|
||||
SHMQueueInit(&(MyProc->myProcLocks[i]));
|
||||
MyProc->recoveryConflictPending = false;
|
||||
|
||||
/* Initialise for sync rep */
|
||||
/* Initialize fields for sync rep */
|
||||
MyProc->waitLSN.xlogid = 0;
|
||||
MyProc->waitLSN.xrecoff = 0;
|
||||
MyProc->syncRepState = SYNC_REP_NOT_WAITING;
|
||||
SHMQueueElemInit(&(MyProc->syncRepLinks));
|
||||
OwnLatch(&MyProc->waitLatch);
|
||||
|
||||
/*
|
||||
* Acquire ownership of the PGPROC's latch, so that we can use WaitLatch.
|
||||
* Note that there's no particular need to do ResetLatch here.
|
||||
*/
|
||||
OwnLatch(&MyProc->procLatch);
|
||||
|
||||
/*
|
||||
* We might be reusing a semaphore that belonged to a failed process. So
|
||||
@ -373,7 +380,6 @@ InitProcessPhase2(void)
|
||||
/*
|
||||
* Arrange to clean that up at backend exit.
|
||||
*/
|
||||
on_shmem_exit(SyncRepCleanupAtProcExit, 0);
|
||||
on_shmem_exit(RemoveProcFromArray, 0);
|
||||
}
|
||||
|
||||
@ -448,8 +454,8 @@ InitAuxiliaryProcess(void)
|
||||
SpinLockRelease(ProcStructLock);
|
||||
|
||||
/*
|
||||
* Initialize all fields of MyProc, except for the semaphore which was
|
||||
* prepared for us by InitProcGlobal.
|
||||
* Initialize all fields of MyProc, except for the semaphore and latch,
|
||||
* which were prepared for us by InitProcGlobal.
|
||||
*/
|
||||
SHMQueueElemInit(&(MyProc->links));
|
||||
MyProc->waitStatus = STATUS_OK;
|
||||
@ -469,6 +475,12 @@ InitAuxiliaryProcess(void)
|
||||
for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
|
||||
SHMQueueInit(&(MyProc->myProcLocks[i]));
|
||||
|
||||
/*
|
||||
* Acquire ownership of the PGPROC's latch, so that we can use WaitLatch.
|
||||
* Note that there's no particular need to do ResetLatch here.
|
||||
*/
|
||||
OwnLatch(&MyProc->procLatch);
|
||||
|
||||
/*
|
||||
* We might be reusing a semaphore that belonged to a failed process. So
|
||||
* be careful and reinitialize its value here. (This is not strictly
|
||||
@ -671,6 +683,9 @@ ProcKill(int code, Datum arg)
|
||||
|
||||
Assert(MyProc != NULL);
|
||||
|
||||
/* Make sure we're out of the sync rep lists */
|
||||
SyncRepCleanupAtProcExit();
|
||||
|
||||
/*
|
||||
* 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
|
||||
@ -678,6 +693,9 @@ ProcKill(int code, Datum arg)
|
||||
*/
|
||||
LWLockReleaseAll();
|
||||
|
||||
/* Release ownership of the process's latch, too */
|
||||
DisownLatch(&MyProc->procLatch);
|
||||
|
||||
SpinLockAcquire(ProcStructLock);
|
||||
|
||||
/* Return PGPROC structure (and semaphore) to appropriate freelist */
|
||||
@ -733,6 +751,9 @@ AuxiliaryProcKill(int code, Datum arg)
|
||||
/* Release any LW locks I am holding (see notes above) */
|
||||
LWLockReleaseAll();
|
||||
|
||||
/* Release ownership of the process's latch, too */
|
||||
DisownLatch(&MyProc->procLatch);
|
||||
|
||||
SpinLockAcquire(ProcStructLock);
|
||||
|
||||
/* Mark auxiliary proc no longer in use */
|
||||
@ -1610,6 +1631,10 @@ handle_sig_alarm(SIGNAL_ARGS)
|
||||
{
|
||||
int save_errno = errno;
|
||||
|
||||
/* SIGALRM is cause for waking anything waiting on the process latch */
|
||||
if (MyProc)
|
||||
SetLatch(&MyProc->procLatch);
|
||||
|
||||
if (deadlock_timeout_active)
|
||||
{
|
||||
deadlock_timeout_active = false;
|
||||
|
Reference in New Issue
Block a user