Unify SIGHUP handling between normal and walsender backends.
authorAndres Freund
Tue, 6 Jun 2017 01:53:42 +0000 (18:53 -0700)
committerAndres Freund
Tue, 6 Jun 2017 02:18:16 +0000 (19:18 -0700)
Because walsender and normal backends share the same main loop it's
problematic to have two different flag variables, set in signal
handlers, indicating a pending configuration reload.  Only certain
walsender commands reach code paths checking for the
variable (START_[LOGICAL_]REPLICATION, CREATE_REPLICATION_SLOT
... LOGICAL, notably not base backups).

This is a bug present since the introduction of walsender, but has
gotten worse in releases since then which allow walsender to do more.

A later patch, not slated for v10, will similarly unify SIGHUP
handling in other types of processes as well.

Author: Petr Jelinek, Andres Freund
Reviewed-By: Michael Paquier
Discussion: https://postgr.es/m/20170423235941[email protected]
Backpatch: 9.2-, bug is present since 9.0

src/backend/replication/walsender.c
src/backend/tcop/postgres.c
src/backend/utils/init/globals.c
src/include/miscadmin.h

index 23a5d506f355cd28935d7006ed50042b49d8aa91..d8735c3aa165afb5bef094357284ad03a6f3ed66 100644 (file)
@@ -175,7 +175,6 @@ static bool streamingDoneReceiving;
 static bool WalSndCaughtUp = false;
 
 /* Flags set by signal handlers for later service in main loop */
-static volatile sig_atomic_t got_SIGHUP = false;
 static volatile sig_atomic_t got_SIGUSR2 = false;
 static volatile sig_atomic_t got_STOPPING = false;
 
@@ -191,7 +190,6 @@ static LogicalDecodingContext *logical_decoding_ctx = NULL;
 static XLogRecPtr logical_startptr = InvalidXLogRecPtr;
 
 /* Signal handlers */
-static void WalSndSigHupHandler(SIGNAL_ARGS);
 static void WalSndLastCycleHandler(SIGNAL_ARGS);
 
 /* Prototypes for private functions */
@@ -1111,9 +1109,9 @@ WalSndWriteData(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId xid,
        CHECK_FOR_INTERRUPTS();
 
        /* Process any requests or signals received recently */
-       if (got_SIGHUP)
+       if (ConfigReloadPending)
        {
-           got_SIGHUP = false;
+           ConfigReloadPending = false;
            ProcessConfigFile(PGC_SIGHUP);
            SyncRepInitConfig();
        }
@@ -1194,9 +1192,9 @@ WalSndWaitForWal(XLogRecPtr loc)
        CHECK_FOR_INTERRUPTS();
 
        /* Process any requests or signals received recently */
-       if (got_SIGHUP)
+       if (ConfigReloadPending)
        {
-           got_SIGHUP = false;
+           ConfigReloadPending = false;
            ProcessConfigFile(PGC_SIGHUP);
            SyncRepInitConfig();
        }
@@ -1854,9 +1852,9 @@ WalSndLoop(WalSndSendDataCallback send_data)
        CHECK_FOR_INTERRUPTS();
 
        /* Process any requests or signals received recently */
-       if (got_SIGHUP)
+       if (ConfigReloadPending)
        {
-           got_SIGHUP = false;
+           ConfigReloadPending = false;
            ProcessConfigFile(PGC_SIGHUP);
            SyncRepInitConfig();
        }
@@ -2633,19 +2631,6 @@ HandleWalSndInitStopping(void)
    }
 }
 
-/* SIGHUP: set flag to re-read config file at next convenient time */
-static void
-WalSndSigHupHandler(SIGNAL_ARGS)
-{
-   int         save_errno = errno;
-
-   got_SIGHUP = true;
-
-   SetLatch(MyLatch);
-
-   errno = save_errno;
-}
-
 /*
  * SIGUSR2: set flag to do a last cycle and shut down afterwards. The WAL
  * sender should already have been switched to WALSNDSTATE_STOPPING at
@@ -2667,7 +2652,7 @@ void
 WalSndSignals(void)
 {
    /* Set up signal handlers */
-   pqsignal(SIGHUP, WalSndSigHupHandler);      /* set flag to read config
+   pqsignal(SIGHUP, PostgresSigHupHandler);    /* set flag to read config
                                                 * file */
    pqsignal(SIGINT, SIG_IGN);  /* not used */
    pqsignal(SIGTERM, die);     /* request shutdown */
index 4721c6e3345eef70d62169b5808e924c13a601ae..12c31fd2f69ae7e2ad2710140cd1171a16beb4df 100644 (file)
@@ -121,13 +121,6 @@ char      *stack_base_ptr = NULL;
 char      *register_stack_base_ptr = NULL;
 #endif
 
-/*
- * Flag to mark SIGHUP. Whenever the main loop comes around it
- * will reread the configuration file. (Better than doing the
- * reading in the signal handler, ey?)
- */
-static volatile sig_atomic_t got_SIGHUP = false;
-
 /*
  * Flag to keep track of whether we have started a transaction.
  * For extended query protocol this has to be remembered across messages.
@@ -196,7 +189,6 @@ static bool IsTransactionExitStmt(Node *parsetree);
 static bool IsTransactionExitStmtList(List *parseTrees);
 static bool IsTransactionStmtList(List *parseTrees);
 static void drop_unnamed_stmt(void);
-static void SigHupHandler(SIGNAL_ARGS);
 static void log_disconnections(int code, Datum arg);
 
 
@@ -2700,13 +2692,19 @@ FloatExceptionHandler(SIGNAL_ARGS)
                       "invalid operation, such as division by zero.")));
 }
 
-/* SIGHUP: set flag to re-read config file at next convenient time */
-static void
-SigHupHandler(SIGNAL_ARGS)
+/*
+ * SIGHUP: set flag to re-read config file at next convenient time.
+ *
+ * Sets the ConfigReloadPending flag, which should be checked at convenient
+ * places inside main loops. (Better than doing the reading in the signal
+ * handler, ey?)
+ */
+void
+PostgresSigHupHandler(SIGNAL_ARGS)
 {
    int         save_errno = errno;
 
-   got_SIGHUP = true;
+   ConfigReloadPending = true;
    SetLatch(MyLatch);
 
    errno = save_errno;
@@ -3631,8 +3629,8 @@ PostgresMain(int argc, char *argv[],
        WalSndSignals();
    else
    {
-       pqsignal(SIGHUP, SigHupHandler);        /* set flag to read config
-                                                * file */
+       pqsignal(SIGHUP, PostgresSigHupHandler);        /* set flag to read config
+                                                        * file */
        pqsignal(SIGINT, StatementCancelHandler);       /* cancel current query */
        pqsignal(SIGTERM, die); /* cancel current query and exit */
 
@@ -4020,9 +4018,9 @@ PostgresMain(int argc, char *argv[],
         * (5) check for any other interesting events that happened while we
         * slept.
         */
-       if (got_SIGHUP)
+       if (ConfigReloadPending)
        {
-           got_SIGHUP = false;
+           ConfigReloadPending = false;
            ProcessConfigFile(PGC_SIGHUP);
        }
 
index 23e594e584113bf469e2a299ee2117de9c41dc54..0487c5a0dfba4f0973903944c2faff65cecfa3a4 100644 (file)
@@ -30,6 +30,7 @@ volatile bool InterruptPending = false;
 volatile bool QueryCancelPending = false;
 volatile bool ProcDiePending = false;
 volatile bool ClientConnectionLost = false;
+volatile sig_atomic_t ConfigReloadPending = false;
 volatile uint32 InterruptHoldoffCount = 0;
 volatile uint32 QueryCancelHoldoffCount = 0;
 volatile uint32 CritSectionCount = 0;
index e0d464e02f1c119c9c218666e71c48c33f34aea4..6eda00f1368546d6d4bf80ee137835296418d3a2 100644 (file)
@@ -23,6 +23,8 @@
 #ifndef MISCADMIN_H
 #define MISCADMIN_H
 
+#include 
+
 #include "pgtime.h"                /* for pg_time_t */
 
 
@@ -80,6 +82,7 @@
 extern PGDLLIMPORT volatile bool InterruptPending;
 extern PGDLLIMPORT volatile bool QueryCancelPending;
 extern PGDLLIMPORT volatile bool ProcDiePending;
+extern PGDLLIMPORT volatile sig_atomic_t ConfigReloadPending;
 
 extern volatile bool ClientConnectionLost;
 
@@ -270,6 +273,8 @@ extern void restore_stack_base(pg_stack_base_t base);
 extern void check_stack_depth(void);
 extern bool stack_is_too_deep(void);
 
+extern void PostgresSigHupHandler(SIGNAL_ARGS);
+
 /* in tcop/utility.c */
 extern void PreventCommandIfReadOnly(const char *cmdname);
 extern void PreventCommandIfParallelMode(const char *cmdname);