| 1 | /*------------------------------------------------------------------------- |
| 2 | * |
| 3 | * walwriter.c |
| 4 | * |
| 5 | * The WAL writer background process is new as of Postgres 8.3. It attempts |
| 6 | * to keep regular backends from having to write out (and fsync) WAL pages. |
| 7 | * Also, it guarantees that transaction commit records that weren't synced |
| 8 | * to disk immediately upon commit (ie, were "asynchronously committed") |
| 9 | * will reach disk within a knowable time --- which, as it happens, is at |
| 10 | * most three times the wal_writer_delay cycle time. |
| 11 | * |
| 12 | * Note that as with the bgwriter for shared buffers, regular backends are |
| 13 | * still empowered to issue WAL writes and fsyncs when the walwriter doesn't |
| 14 | * keep up. This means that the WALWriter is not an essential process and |
| 15 | * can shutdown quickly when requested. |
| 16 | * |
| 17 | * Because the walwriter's cycle is directly linked to the maximum delay |
| 18 | * before async-commit transactions are guaranteed committed, it's probably |
| 19 | * unwise to load additional functionality onto it. For instance, if you've |
| 20 | * got a yen to create xlog segments further in advance, that'd be better done |
| 21 | * in bgwriter than in walwriter. |
| 22 | * |
| 23 | * The walwriter is started by the postmaster as soon as the startup subprocess |
| 24 | * finishes. It remains alive until the postmaster commands it to terminate. |
| 25 | * Normal termination is by SIGTERM, which instructs the walwriter to exit(0). |
| 26 | * Emergency termination is by SIGQUIT; like any backend, the walwriter will |
| 27 | * simply abort and exit on SIGQUIT. |
| 28 | * |
| 29 | * If the walwriter exits unexpectedly, the postmaster treats that the same |
| 30 | * as a backend crash: shared memory may be corrupted, so remaining backends |
| 31 | * should be killed by SIGQUIT and then a recovery cycle started. |
| 32 | * |
| 33 | * |
| 34 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
| 35 | * |
| 36 | * |
| 37 | * IDENTIFICATION |
| 38 | * src/backend/postmaster/walwriter.c |
| 39 | * |
| 40 | *------------------------------------------------------------------------- |
| 41 | */ |
| 42 | #include "postgres.h" |
| 43 | |
| 44 | #include <signal.h> |
| 45 | #include <unistd.h> |
| 46 | |
| 47 | #include "access/xlog.h" |
| 48 | #include "libpq/pqsignal.h" |
| 49 | #include "miscadmin.h" |
| 50 | #include "pgstat.h" |
| 51 | #include "postmaster/walwriter.h" |
| 52 | #include "storage/bufmgr.h" |
| 53 | #include "storage/condition_variable.h" |
| 54 | #include "storage/fd.h" |
| 55 | #include "storage/ipc.h" |
| 56 | #include "storage/lwlock.h" |
| 57 | #include "storage/proc.h" |
| 58 | #include "storage/smgr.h" |
| 59 | #include "utils/guc.h" |
| 60 | #include "utils/hsearch.h" |
| 61 | #include "utils/memutils.h" |
| 62 | #include "utils/resowner.h" |
| 63 | |
| 64 | |
| 65 | /* |
| 66 | * GUC parameters |
| 67 | */ |
| 68 | int WalWriterDelay = 200; |
| 69 | int WalWriterFlushAfter = 128; |
| 70 | |
| 71 | /* |
| 72 | * Number of do-nothing loops before lengthening the delay time, and the |
| 73 | * multiplier to apply to WalWriterDelay when we do decide to hibernate. |
| 74 | * (Perhaps these need to be configurable?) |
| 75 | */ |
| 76 | #define LOOPS_UNTIL_HIBERNATE 50 |
| 77 | #define HIBERNATE_FACTOR 25 |
| 78 | |
| 79 | /* |
| 80 | * Flags set by interrupt handlers for later service in the main loop. |
| 81 | */ |
| 82 | static volatile sig_atomic_t got_SIGHUP = false; |
| 83 | static volatile sig_atomic_t shutdown_requested = false; |
| 84 | |
| 85 | /* Signal handlers */ |
| 86 | static void wal_quickdie(SIGNAL_ARGS); |
| 87 | static void WalSigHupHandler(SIGNAL_ARGS); |
| 88 | static void WalShutdownHandler(SIGNAL_ARGS); |
| 89 | static void walwriter_sigusr1_handler(SIGNAL_ARGS); |
| 90 | |
| 91 | /* |
| 92 | * Main entry point for walwriter process |
| 93 | * |
| 94 | * This is invoked from AuxiliaryProcessMain, which has already created the |
| 95 | * basic execution environment, but not enabled signals yet. |
| 96 | */ |
| 97 | void |
| 98 | WalWriterMain(void) |
| 99 | { |
| 100 | sigjmp_buf local_sigjmp_buf; |
| 101 | MemoryContext walwriter_context; |
| 102 | int left_till_hibernate; |
| 103 | bool hibernating; |
| 104 | |
| 105 | /* |
| 106 | * Properly accept or ignore signals the postmaster might send us |
| 107 | * |
| 108 | * We have no particular use for SIGINT at the moment, but seems |
| 109 | * reasonable to treat like SIGTERM. |
| 110 | */ |
| 111 | pqsignal(SIGHUP, WalSigHupHandler); /* set flag to read config file */ |
| 112 | pqsignal(SIGINT, WalShutdownHandler); /* request shutdown */ |
| 113 | pqsignal(SIGTERM, WalShutdownHandler); /* request shutdown */ |
| 114 | pqsignal(SIGQUIT, wal_quickdie); /* hard crash time */ |
| 115 | pqsignal(SIGALRM, SIG_IGN); |
| 116 | pqsignal(SIGPIPE, SIG_IGN); |
| 117 | pqsignal(SIGUSR1, walwriter_sigusr1_handler); |
| 118 | pqsignal(SIGUSR2, SIG_IGN); /* not used */ |
| 119 | |
| 120 | /* |
| 121 | * Reset some signals that are accepted by postmaster but not here |
| 122 | */ |
| 123 | pqsignal(SIGCHLD, SIG_DFL); |
| 124 | |
| 125 | /* We allow SIGQUIT (quickdie) at all times */ |
| 126 | sigdelset(&BlockSig, SIGQUIT); |
| 127 | |
| 128 | /* |
| 129 | * Create a memory context that we will do all our work in. We do this so |
| 130 | * that we can reset the context during error recovery and thereby avoid |
| 131 | * possible memory leaks. Formerly this code just ran in |
| 132 | * TopMemoryContext, but resetting that would be a really bad idea. |
| 133 | */ |
| 134 | walwriter_context = AllocSetContextCreate(TopMemoryContext, |
| 135 | "Wal Writer" , |
| 136 | ALLOCSET_DEFAULT_SIZES); |
| 137 | MemoryContextSwitchTo(walwriter_context); |
| 138 | |
| 139 | /* |
| 140 | * If an exception is encountered, processing resumes here. |
| 141 | * |
| 142 | * This code is heavily based on bgwriter.c, q.v. |
| 143 | */ |
| 144 | if (sigsetjmp(local_sigjmp_buf, 1) != 0) |
| 145 | { |
| 146 | /* Since not using PG_TRY, must reset error stack by hand */ |
| 147 | error_context_stack = NULL; |
| 148 | |
| 149 | /* Prevent interrupts while cleaning up */ |
| 150 | HOLD_INTERRUPTS(); |
| 151 | |
| 152 | /* Report the error to the server log */ |
| 153 | EmitErrorReport(); |
| 154 | |
| 155 | /* |
| 156 | * These operations are really just a minimal subset of |
| 157 | * AbortTransaction(). We don't have very many resources to worry |
| 158 | * about in walwriter, but we do have LWLocks, and perhaps buffers? |
| 159 | */ |
| 160 | LWLockReleaseAll(); |
| 161 | ConditionVariableCancelSleep(); |
| 162 | pgstat_report_wait_end(); |
| 163 | AbortBufferIO(); |
| 164 | UnlockBuffers(); |
| 165 | ReleaseAuxProcessResources(false); |
| 166 | AtEOXact_Buffers(false); |
| 167 | AtEOXact_SMgr(); |
| 168 | AtEOXact_Files(false); |
| 169 | AtEOXact_HashTables(false); |
| 170 | |
| 171 | /* |
| 172 | * Now return to normal top-level context and clear ErrorContext for |
| 173 | * next time. |
| 174 | */ |
| 175 | MemoryContextSwitchTo(walwriter_context); |
| 176 | FlushErrorState(); |
| 177 | |
| 178 | /* Flush any leaked data in the top-level context */ |
| 179 | MemoryContextResetAndDeleteChildren(walwriter_context); |
| 180 | |
| 181 | /* Now we can allow interrupts again */ |
| 182 | RESUME_INTERRUPTS(); |
| 183 | |
| 184 | /* |
| 185 | * Sleep at least 1 second after any error. A write error is likely |
| 186 | * to be repeated, and we don't want to be filling the error logs as |
| 187 | * fast as we can. |
| 188 | */ |
| 189 | pg_usleep(1000000L); |
| 190 | |
| 191 | /* |
| 192 | * Close all open files after any error. This is helpful on Windows, |
| 193 | * where holding deleted files open causes various strange errors. |
| 194 | * It's not clear we need it elsewhere, but shouldn't hurt. |
| 195 | */ |
| 196 | smgrcloseall(); |
| 197 | } |
| 198 | |
| 199 | /* We can now handle ereport(ERROR) */ |
| 200 | PG_exception_stack = &local_sigjmp_buf; |
| 201 | |
| 202 | /* |
| 203 | * Unblock signals (they were blocked when the postmaster forked us) |
| 204 | */ |
| 205 | PG_SETMASK(&UnBlockSig); |
| 206 | |
| 207 | /* |
| 208 | * Reset hibernation state after any error. |
| 209 | */ |
| 210 | left_till_hibernate = LOOPS_UNTIL_HIBERNATE; |
| 211 | hibernating = false; |
| 212 | SetWalWriterSleeping(false); |
| 213 | |
| 214 | /* |
| 215 | * Advertise our latch that backends can use to wake us up while we're |
| 216 | * sleeping. |
| 217 | */ |
| 218 | ProcGlobal->walwriterLatch = &MyProc->procLatch; |
| 219 | |
| 220 | /* |
| 221 | * Loop forever |
| 222 | */ |
| 223 | for (;;) |
| 224 | { |
| 225 | long cur_timeout; |
| 226 | |
| 227 | /* |
| 228 | * Advertise whether we might hibernate in this cycle. We do this |
| 229 | * before resetting the latch to ensure that any async commits will |
| 230 | * see the flag set if they might possibly need to wake us up, and |
| 231 | * that we won't miss any signal they send us. (If we discover work |
| 232 | * to do in the last cycle before we would hibernate, the global flag |
| 233 | * will be set unnecessarily, but little harm is done.) But avoid |
| 234 | * touching the global flag if it doesn't need to change. |
| 235 | */ |
| 236 | if (hibernating != (left_till_hibernate <= 1)) |
| 237 | { |
| 238 | hibernating = (left_till_hibernate <= 1); |
| 239 | SetWalWriterSleeping(hibernating); |
| 240 | } |
| 241 | |
| 242 | /* Clear any already-pending wakeups */ |
| 243 | ResetLatch(MyLatch); |
| 244 | |
| 245 | /* |
| 246 | * Process any requests or signals received recently. |
| 247 | */ |
| 248 | if (got_SIGHUP) |
| 249 | { |
| 250 | got_SIGHUP = false; |
| 251 | ProcessConfigFile(PGC_SIGHUP); |
| 252 | } |
| 253 | if (shutdown_requested) |
| 254 | { |
| 255 | /* Normal exit from the walwriter is here */ |
| 256 | proc_exit(0); /* done */ |
| 257 | } |
| 258 | |
| 259 | /* |
| 260 | * Do what we're here for; then, if XLogBackgroundFlush() found useful |
| 261 | * work to do, reset hibernation counter. |
| 262 | */ |
| 263 | if (XLogBackgroundFlush()) |
| 264 | left_till_hibernate = LOOPS_UNTIL_HIBERNATE; |
| 265 | else if (left_till_hibernate > 0) |
| 266 | left_till_hibernate--; |
| 267 | |
| 268 | /* |
| 269 | * Sleep until we are signaled or WalWriterDelay has elapsed. If we |
| 270 | * haven't done anything useful for quite some time, lengthen the |
| 271 | * sleep time so as to reduce the server's idle power consumption. |
| 272 | */ |
| 273 | if (left_till_hibernate > 0) |
| 274 | cur_timeout = WalWriterDelay; /* in ms */ |
| 275 | else |
| 276 | cur_timeout = WalWriterDelay * HIBERNATE_FACTOR; |
| 277 | |
| 278 | (void) WaitLatch(MyLatch, |
| 279 | WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH, |
| 280 | cur_timeout, |
| 281 | WAIT_EVENT_WAL_WRITER_MAIN); |
| 282 | } |
| 283 | } |
| 284 | |
| 285 | |
| 286 | /* -------------------------------- |
| 287 | * signal handler routines |
| 288 | * -------------------------------- |
| 289 | */ |
| 290 | |
| 291 | /* |
| 292 | * wal_quickdie() occurs when signalled SIGQUIT by the postmaster. |
| 293 | * |
| 294 | * Some backend has bought the farm, |
| 295 | * so we need to stop what we're doing and exit. |
| 296 | */ |
| 297 | static void |
| 298 | wal_quickdie(SIGNAL_ARGS) |
| 299 | { |
| 300 | /* |
| 301 | * We DO NOT want to run proc_exit() or atexit() callbacks -- we're here |
| 302 | * because shared memory may be corrupted, so we don't want to try to |
| 303 | * clean up our transaction. Just nail the windows shut and get out of |
| 304 | * town. The callbacks wouldn't be safe to run from a signal handler, |
| 305 | * anyway. |
| 306 | * |
| 307 | * Note we do _exit(2) not _exit(0). This is to force the postmaster into |
| 308 | * a system reset cycle if someone sends a manual SIGQUIT to a random |
| 309 | * backend. This is necessary precisely because we don't clean up our |
| 310 | * shared memory state. (The "dead man switch" mechanism in pmsignal.c |
| 311 | * should ensure the postmaster sees this as a crash, too, but no harm in |
| 312 | * being doubly sure.) |
| 313 | */ |
| 314 | _exit(2); |
| 315 | } |
| 316 | |
| 317 | /* SIGHUP: set flag to re-read config file at next convenient time */ |
| 318 | static void |
| 319 | WalSigHupHandler(SIGNAL_ARGS) |
| 320 | { |
| 321 | int save_errno = errno; |
| 322 | |
| 323 | got_SIGHUP = true; |
| 324 | SetLatch(MyLatch); |
| 325 | |
| 326 | errno = save_errno; |
| 327 | } |
| 328 | |
| 329 | /* SIGTERM: set flag to exit normally */ |
| 330 | static void |
| 331 | WalShutdownHandler(SIGNAL_ARGS) |
| 332 | { |
| 333 | int save_errno = errno; |
| 334 | |
| 335 | shutdown_requested = true; |
| 336 | SetLatch(MyLatch); |
| 337 | |
| 338 | errno = save_errno; |
| 339 | } |
| 340 | |
| 341 | /* SIGUSR1: used for latch wakeups */ |
| 342 | static void |
| 343 | walwriter_sigusr1_handler(SIGNAL_ARGS) |
| 344 | { |
| 345 | int save_errno = errno; |
| 346 | |
| 347 | latch_sigusr1_handler(); |
| 348 | |
| 349 | errno = save_errno; |
| 350 | } |
| 351 | |