Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Unify SIGHUP handling between normal and walsender backends.
authorAndres Freund <andres@anarazel.de>
Tue, 6 Jun 2017 01:53:42 +0000 (18:53 -0700)
committerAndres Freund <andres@anarazel.de>
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.qosiuoyqprq4nu7v@alap3.anarazel.de
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 8cd839bda8399c50253dfdc7cd008f41d1b5a7f4..6304e2e46c0bd313d0e2603d8e00c46b1731a3c4 100644 (file)
@@ -174,7 +174,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;
 
@@ -190,7 +189,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 */
@@ -1104,9 +1102,9 @@ WalSndWriteData(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId xid,
            exit(1);
 
        /* Process any requests or signals received recently */
-       if (got_SIGHUP)
+       if (ConfigReloadPending)
        {
-           got_SIGHUP = false;
+           ConfigReloadPending = false;
            ProcessConfigFile(PGC_SIGHUP);
            SyncRepInitConfig();
        }
@@ -1188,9 +1186,9 @@ WalSndWaitForWal(XLogRecPtr loc)
            exit(1);
 
        /* Process any requests or signals received recently */
-       if (got_SIGHUP)
+       if (ConfigReloadPending)
        {
-           got_SIGHUP = false;
+           ConfigReloadPending = false;
            ProcessConfigFile(PGC_SIGHUP);
            SyncRepInitConfig();
        }
@@ -1843,9 +1841,9 @@ WalSndLoop(WalSndSendDataCallback send_data)
            exit(1);
 
        /* Process any requests or signals received recently */
-       if (got_SIGHUP)
+       if (ConfigReloadPending)
        {
-           got_SIGHUP = false;
+           ConfigReloadPending = false;
            ProcessConfigFile(PGC_SIGHUP);
            SyncRepInitConfig();
        }
@@ -2636,19 +2634,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;
-   if (MyWalSnd)
-       SetLatch(&MyWalSnd->latch);
-
-   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
@@ -2670,7 +2655,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 8b9c3d4feb9ba2356d94fa8a1fd126713884a0bc..7a1b49a92758f0934ac71cbe6a5b034658260580 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);
 
 
@@ -2676,13 +2668,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;
    if (MyProc)
        SetLatch(&MyProc->procLatch);
 
@@ -3674,8 +3672,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 */
 
@@ -4069,9 +4067,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 342105f0174b233913fec161cfa1014c18fcc88a..67c02f6e4c50f919340c73edbbb2c068ddcaf694 100644 (file)
@@ -31,6 +31,7 @@ volatile bool QueryCancelPending = false;
 volatile bool ProcDiePending = false;
 volatile bool ClientConnectionLost = false;
 volatile bool ImmediateInterruptOK = false;
+volatile sig_atomic_t ConfigReloadPending = false;
 volatile uint32 InterruptHoldoffCount = 0;
 volatile uint32 QueryCancelHoldoffCount = 0;
 volatile uint32 CritSectionCount = 0;
index dec110650ec6df4100f85a754f7cb23bab39ac2a..5ecdb255ed3faa6036d0546e32ccb90ed8a80c0f 100644 (file)
@@ -23,6 +23,8 @@
 #ifndef MISCADMIN_H
 #define MISCADMIN_H
 
+#include <signal.h>
+
 #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 PreventCommandDuringRecovery(const char *cmdname);