diff options
Diffstat (limited to 'src/backend/replication/walreceiver.c')
-rw-r--r-- | src/backend/replication/walreceiver.c | 66 |
1 files changed, 17 insertions, 49 deletions
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c index c463c119eff..17b5b8be999 100644 --- a/src/backend/replication/walreceiver.c +++ b/src/backend/replication/walreceiver.c @@ -112,28 +112,7 @@ static struct static StringInfoData reply_message; static StringInfoData incoming_message; -/* - * About SIGTERM handling: - * - * We can't just exit(1) within SIGTERM signal handler, because the signal - * might arrive in the middle of some critical operation, like while we're - * holding a spinlock. We also can't just set a flag in signal handler and - * check it in the main loop, because we perform some blocking operations - * like libpqrcv_PQexec(), which can take a long time to finish. - * - * We use a combined approach: When WalRcvImmediateInterruptOK is true, it's - * safe for the signal handler to elog(FATAL) immediately. Otherwise it just - * sets got_SIGTERM flag, which is checked in the main loop when convenient. - * - * This is very much like what regular backends do with ImmediateInterruptOK, - * ProcessInterrupts() etc. - */ -static volatile bool WalRcvImmediateInterruptOK = false; - /* Prototypes for private functions */ -static void ProcessWalRcvInterrupts(void); -static void EnableWalRcvImmediateExit(void); -static void DisableWalRcvImmediateExit(void); static void WalRcvFetchTimeLineHistoryFiles(TimeLineID first, TimeLineID last); static void WalRcvWaitForStartPosition(XLogRecPtr *startpoint, TimeLineID *startpointTLI); static void WalRcvDie(int code, Datum arg); @@ -151,7 +130,20 @@ static void WalRcvShutdownHandler(SIGNAL_ARGS); static void WalRcvQuickDieHandler(SIGNAL_ARGS); -static void +/* + * Process any interrupts the walreceiver process may have received. + * This should be called any time the process's latch has become set. + * + * Currently, only SIGTERM is of interest. We can't just exit(1) within the + * SIGTERM signal handler, because the signal might arrive in the middle of + * some critical operation, like while we're holding a spinlock. Instead, the + * signal handler sets a flag variable as well as setting the process's latch. + * We must check the flag (by calling ProcessWalRcvInterrupts) anytime the + * latch has become set. Operations that could block for a long time, such as + * reading from a remote server, must pay attention to the latch too; see + * libpqrcv_PQgetResult for example. + */ +void ProcessWalRcvInterrupts(void) { /* @@ -163,26 +155,12 @@ ProcessWalRcvInterrupts(void) if (got_SIGTERM) { - WalRcvImmediateInterruptOK = false; ereport(FATAL, (errcode(ERRCODE_ADMIN_SHUTDOWN), errmsg("terminating walreceiver process due to administrator command"))); } } -static void -EnableWalRcvImmediateExit(void) -{ - WalRcvImmediateInterruptOK = true; - ProcessWalRcvInterrupts(); -} - -static void -DisableWalRcvImmediateExit(void) -{ - WalRcvImmediateInterruptOK = false; - ProcessWalRcvInterrupts(); -} /* Main entry point for walreceiver process */ void @@ -302,12 +280,10 @@ WalReceiverMain(void) PG_SETMASK(&UnBlockSig); /* Establish the connection to the primary for XLOG streaming */ - EnableWalRcvImmediateExit(); wrconn = walrcv_connect(conninfo, false, "walreceiver", &err); if (!wrconn) ereport(ERROR, (errmsg("could not connect to the primary server: %s", err))); - DisableWalRcvImmediateExit(); /* * Save user-visible connection string. This clobbers the original @@ -347,7 +323,6 @@ WalReceiverMain(void) * Check that we're connected to a valid server using the * IDENTIFY_SYSTEM replication command. */ - EnableWalRcvImmediateExit(); primary_sysid = walrcv_identify_system(wrconn, &primaryTLI, &server_version); @@ -360,7 +335,6 @@ WalReceiverMain(void) errdetail("The primary's identifier is %s, the standby's identifier is %s.", primary_sysid, standby_sysid))); } - DisableWalRcvImmediateExit(); /* * Confirm that the current timeline of the primary is the same or @@ -521,6 +495,8 @@ WalReceiverMain(void) if (rc & WL_LATCH_SET) { ResetLatch(walrcv->latch); + ProcessWalRcvInterrupts(); + if (walrcv->force_reply) { /* @@ -598,9 +574,7 @@ WalReceiverMain(void) * The backend finished streaming. Exit streaming COPY-mode from * our side, too. */ - EnableWalRcvImmediateExit(); walrcv_endstreaming(wrconn, &primaryTLI); - DisableWalRcvImmediateExit(); /* * If the server had switched to a new timeline that we didn't @@ -754,9 +728,7 @@ WalRcvFetchTimeLineHistoryFiles(TimeLineID first, TimeLineID last) (errmsg("fetching timeline history file for timeline %u from primary server", tli))); - EnableWalRcvImmediateExit(); walrcv_readtimelinehistoryfile(wrconn, tli, &fname, &content, &len); - DisableWalRcvImmediateExit(); /* * Check that the filename on the master matches what we @@ -833,7 +805,7 @@ WalRcvSigUsr1Handler(SIGNAL_ARGS) errno = save_errno; } -/* SIGTERM: set flag for main loop, or shutdown immediately if safe */ +/* SIGTERM: set flag for ProcessWalRcvInterrupts */ static void WalRcvShutdownHandler(SIGNAL_ARGS) { @@ -844,10 +816,6 @@ WalRcvShutdownHandler(SIGNAL_ARGS) if (WalRcv->latch) SetLatch(WalRcv->latch); - /* Don't joggle the elbow of proc_exit */ - if (!proc_exit_inprogress && WalRcvImmediateInterruptOK) - ProcessWalRcvInterrupts(); - errno = save_errno; } |