
Go to the source code of this file.
Functions | |
| void | WalWriterMain (void) __attribute__((noreturn)) |
Variables | |
| int | WalWriterDelay |
| void WalWriterMain | ( | void | ) |
Definition at line 97 of file walwriter.c.
References AbortBufferIO(), ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, AllocSetContextCreate(), AtEOXact_Buffers(), AtEOXact_Files(), AtEOXact_HashTables(), AtEOXact_SMgr(), BlockSig, CurrentResourceOwner, elog, EmitErrorReport(), error_context_stack, FATAL, FlushErrorState(), got_SIGHUP, HOLD_INTERRUPTS, LWLockReleaseAll(), MemoryContextResetAndDeleteChildren(), MemoryContextSwitchTo(), MyProc, NULL, PG_exception_stack, PG_SETMASK, pg_usleep(), PGC_SIGHUP, pqsignal(), proc_exit(), ProcessConfigFile(), ProcGlobal, PGPROC::procLatch, ResetLatch(), RESOURCE_RELEASE_BEFORE_LOCKS, ResourceOwnerCreate(), ResourceOwnerRelease(), RESUME_INTERRUPTS, SetWalWriterSleeping(), shutdown_requested, SIG_DFL, SIG_IGN, SIGALRM, SIGCHLD, SIGCONT, sigdelset, SIGHUP, sigjmp_buf, SIGPIPE, SIGQUIT, sigsetjmp, SIGTTIN, SIGTTOU, SIGUSR1, SIGUSR2, SIGWINCH, smgrcloseall(), TopMemoryContext, UnBlockSig, UnlockBuffers(), WaitLatch(), wal_quickdie(), WalShutdownHandler(), WalSigHupHandler(), walwriter_sigusr1_handler(), WalWriterDelay, PROC_HDR::walwriterLatch, WL_LATCH_SET, WL_POSTMASTER_DEATH, WL_TIMEOUT, and XLogBackgroundFlush().
Referenced by AuxiliaryProcessMain().
{
sigjmp_buf local_sigjmp_buf;
MemoryContext walwriter_context;
int left_till_hibernate;
bool hibernating;
/*
* If possible, make this process a group leader, so that the postmaster
* can signal any child processes too. (walwriter probably never has any
* child processes, but for consistency we make all postmaster child
* processes do this.)
*/
#ifdef HAVE_SETSID
if (setsid() < 0)
elog(FATAL, "setsid() failed: %m");
#endif
/*
* Properly accept or ignore signals the postmaster might send us
*
* We have no particular use for SIGINT at the moment, but seems
* reasonable to treat like SIGTERM.
*/
pqsignal(SIGHUP, WalSigHupHandler); /* set flag to read config file */
pqsignal(SIGINT, WalShutdownHandler); /* request shutdown */
pqsignal(SIGTERM, WalShutdownHandler); /* request shutdown */
pqsignal(SIGQUIT, wal_quickdie); /* hard crash time */
pqsignal(SIGALRM, SIG_IGN);
pqsignal(SIGPIPE, SIG_IGN);
pqsignal(SIGUSR1, walwriter_sigusr1_handler);
pqsignal(SIGUSR2, SIG_IGN); /* not used */
/*
* Reset some signals that are accepted by postmaster but not here
*/
pqsignal(SIGCHLD, SIG_DFL);
pqsignal(SIGTTIN, SIG_DFL);
pqsignal(SIGTTOU, SIG_DFL);
pqsignal(SIGCONT, SIG_DFL);
pqsignal(SIGWINCH, SIG_DFL);
/* We allow SIGQUIT (quickdie) at all times */
sigdelset(&BlockSig, SIGQUIT);
/*
* Create a resource owner to keep track of our resources (not clear that
* we need this, but may as well have one).
*/
CurrentResourceOwner = ResourceOwnerCreate(NULL, "Wal Writer");
/*
* Create a memory context that we will do all our work in. We do this so
* that we can reset the context during error recovery and thereby avoid
* possible memory leaks. Formerly this code just ran in
* TopMemoryContext, but resetting that would be a really bad idea.
*/
walwriter_context = AllocSetContextCreate(TopMemoryContext,
"Wal Writer",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
MemoryContextSwitchTo(walwriter_context);
/*
* If an exception is encountered, processing resumes here.
*
* This code is heavily based on bgwriter.c, q.v.
*/
if (sigsetjmp(local_sigjmp_buf, 1) != 0)
{
/* Since not using PG_TRY, must reset error stack by hand */
error_context_stack = NULL;
/* Prevent interrupts while cleaning up */
HOLD_INTERRUPTS();
/* Report the error to the server log */
EmitErrorReport();
/*
* These operations are really just a minimal subset of
* AbortTransaction(). We don't have very many resources to worry
* about in walwriter, but we do have LWLocks, and perhaps buffers?
*/
LWLockReleaseAll();
AbortBufferIO();
UnlockBuffers();
/* buffer pins are released here: */
ResourceOwnerRelease(CurrentResourceOwner,
RESOURCE_RELEASE_BEFORE_LOCKS,
false, true);
/* we needn't bother with the other ResourceOwnerRelease phases */
AtEOXact_Buffers(false);
AtEOXact_SMgr();
AtEOXact_Files();
AtEOXact_HashTables(false);
/*
* Now return to normal top-level context and clear ErrorContext for
* next time.
*/
MemoryContextSwitchTo(walwriter_context);
FlushErrorState();
/* Flush any leaked data in the top-level context */
MemoryContextResetAndDeleteChildren(walwriter_context);
/* Now we can allow interrupts again */
RESUME_INTERRUPTS();
/*
* Sleep at least 1 second after any error. A write error is likely
* to be repeated, and we don't want to be filling the error logs as
* fast as we can.
*/
pg_usleep(1000000L);
/*
* Close all open files after any error. This is helpful on Windows,
* where holding deleted files open causes various strange errors.
* It's not clear we need it elsewhere, but shouldn't hurt.
*/
smgrcloseall();
}
/* We can now handle ereport(ERROR) */
PG_exception_stack = &local_sigjmp_buf;
/*
* Unblock signals (they were blocked when the postmaster forked us)
*/
PG_SETMASK(&UnBlockSig);
/*
* Reset hibernation state after any error.
*/
left_till_hibernate = LOOPS_UNTIL_HIBERNATE;
hibernating = false;
SetWalWriterSleeping(false);
/*
* Advertise our latch that backends can use to wake us up while we're
* sleeping.
*/
ProcGlobal->walwriterLatch = &MyProc->procLatch;
/*
* Loop forever
*/
for (;;)
{
long cur_timeout;
int rc;
/*
* Advertise whether we might hibernate in this cycle. We do this
* before resetting the latch to ensure that any async commits will
* see the flag set if they might possibly need to wake us up, and
* that we won't miss any signal they send us. (If we discover work
* to do in the last cycle before we would hibernate, the global flag
* will be set unnecessarily, but little harm is done.) But avoid
* touching the global flag if it doesn't need to change.
*/
if (hibernating != (left_till_hibernate <= 1))
{
hibernating = (left_till_hibernate <= 1);
SetWalWriterSleeping(hibernating);
}
/* Clear any already-pending wakeups */
ResetLatch(&MyProc->procLatch);
/*
* Process any requests or signals received recently.
*/
if (got_SIGHUP)
{
got_SIGHUP = false;
ProcessConfigFile(PGC_SIGHUP);
}
if (shutdown_requested)
{
/* Normal exit from the walwriter is here */
proc_exit(0); /* done */
}
/*
* Do what we're here for; then, if XLogBackgroundFlush() found useful
* work to do, reset hibernation counter.
*/
if (XLogBackgroundFlush())
left_till_hibernate = LOOPS_UNTIL_HIBERNATE;
else if (left_till_hibernate > 0)
left_till_hibernate--;
/*
* Sleep until we are signaled or WalWriterDelay has elapsed. If we
* haven't done anything useful for quite some time, lengthen the
* sleep time so as to reduce the server's idle power consumption.
*/
if (left_till_hibernate > 0)
cur_timeout = WalWriterDelay; /* in ms */
else
cur_timeout = WalWriterDelay * HIBERNATE_FACTOR;
rc = WaitLatch(&MyProc->procLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
cur_timeout);
/*
* Emergency bailout if postmaster has died. This is to avoid the
* necessity for manual cleanup of all postmaster children.
*/
if (rc & WL_POSTMASTER_DEATH)
exit(1);
}
}
| int WalWriterDelay |
Definition at line 68 of file walwriter.c.
Referenced by WalWriterMain().
1.7.1