* Main entry point for checkpointer process * * This is invoked from AuxiliaryProcessMain, which has already created the * basic execution environment, but not enabled signals yet. */
| 182 | * basic execution environment, but not enabled signals yet. |
| 183 | */ |
| 184 | void |
| 185 | CheckpointerMain(void) |
| 186 | { |
| 187 | sigjmp_buf local_sigjmp_buf; |
| 188 | MemoryContext checkpointer_context; |
| 189 | |
| 190 | CheckpointerShmem->checkpointer_pid = MyProcPid; |
| 191 | |
| 192 | /* |
| 193 | * Properly accept or ignore signals the postmaster might send us |
| 194 | * |
| 195 | * Note: we deliberately ignore SIGTERM, because during a standard Unix |
| 196 | * system shutdown cycle, init will SIGTERM all processes at once. We |
| 197 | * want to wait for the backends to exit, whereupon the postmaster will |
| 198 | * tell us it's okay to shut down (via SIGUSR2). |
| 199 | */ |
| 200 | pqsignal(SIGHUP, SignalHandlerForConfigReload); |
| 201 | pqsignal(SIGINT, ReqCheckpointHandler); /* request checkpoint */ |
| 202 | pqsignal(SIGTERM, SIG_IGN); /* ignore SIGTERM */ |
| 203 | /* SIGQUIT handler was already set up by InitPostmasterChild */ |
| 204 | pqsignal(SIGALRM, SIG_IGN); |
| 205 | pqsignal(SIGPIPE, SIG_IGN); |
| 206 | pqsignal(SIGUSR1, procsignal_sigusr1_handler); |
| 207 | pqsignal(SIGUSR2, SignalHandlerForShutdownRequest); |
| 208 | |
| 209 | /* |
| 210 | * Reset some signals that are accepted by postmaster but not here |
| 211 | */ |
| 212 | pqsignal(SIGCHLD, SIG_DFL); |
| 213 | |
| 214 | /* |
| 215 | * Initialize so that first time-driven event happens at the correct time. |
| 216 | */ |
| 217 | last_checkpoint_time = last_xlog_switch_time = (pg_time_t) time(NULL); |
| 218 | |
| 219 | /* |
| 220 | * Create a memory context that we will do all our work in. We do this so |
| 221 | * that we can reset the context during error recovery and thereby avoid |
| 222 | * possible memory leaks. Formerly this code just ran in |
| 223 | * TopMemoryContext, but resetting that would be a really bad idea. |
| 224 | */ |
| 225 | checkpointer_context = AllocSetContextCreate(TopMemoryContext, |
| 226 | "Checkpointer", |
| 227 | ALLOCSET_DEFAULT_SIZES); |
| 228 | MemoryContextSwitchTo(checkpointer_context); |
| 229 | |
| 230 | /* |
| 231 | * If an exception is encountered, processing resumes here. |
| 232 | * |
| 233 | * You might wonder why this isn't coded as an infinite loop around a |
| 234 | * PG_TRY construct. The reason is that this is the bottom of the |
| 235 | * exception stack, and so with PG_TRY there would be no exception handler |
| 236 | * in force at all during the CATCH part. By leaving the outermost setjmp |
| 237 | * always active, we have at least some chance of recovering from an error |
| 238 | * during error recovery. (If we get into an infinite loop thereby, it |
| 239 | * will soon be stopped by overflow of elog.c's internal state stack.) |
| 240 | * |
| 241 | * Note that we use sigsetjmp(..., 1), so that the prevailing signal mask |
no test coverage detected