summaryrefslogtreecommitdiff
path: root/src/backend/postmaster/postmaster.c
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2012-07-16 18:43:21 -0400
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2012-07-16 22:55:33 -0400
commitf34c68f09671c4566854c7e20e9253d4f335c0b0 (patch)
treedcfea396da6622644aca0cf35799e6cc13fa1137 /src/backend/postmaster/postmaster.c
parentdd16f9480ac67ab0c6b0102d110cd5121ed9ab46 (diff)
Introduce timeout handling framework
Management of timeouts was getting a little cumbersome; what we originally had was more than enough back when we were only concerned about deadlocks and query cancel; however, when we added timeouts for standby processes, the code got considerably messier. Since there are plans to add more complex timeouts, this seems a good time to introduce a central timeout handling module. External modules register their timeout handlers during process initialization, and later enable and disable them as they see fit using a simple API; timeout.c is in charge of keeping track of which timeouts are in effect at any time, installing a common SIGALRM signal handler, and calling setitimer() as appropriate to ensure timely firing of external handlers. timeout.c additionally supports pluggable modules to add their own timeouts, though this capability isn't exercised anywhere yet. Additionally, as of this commit, walsender processes are aware of timeouts; we had a preexisting bug there that made those ignore SIGALRM, thus being subject to unhandled deadlocks, particularly during the authentication phase. This has already been fixed in back branches in commit 0bf8eb2a, which see for more details. Main author: Zoltán Böszörményi Some review and cleanup by Álvaro Herrera Extensive reworking by Tom Lane
Diffstat (limited to 'src/backend/postmaster/postmaster.c')
-rw-r--r--src/backend/postmaster/postmaster.c36
1 files changed, 28 insertions, 8 deletions
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 45f6ac624eb..0be3230c2a5 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -112,12 +112,12 @@
#include "storage/ipc.h"
#include "storage/pg_shmem.h"
#include "storage/pmsignal.h"
-#include "storage/proc.h"
#include "tcop/tcopprot.h"
#include "utils/builtins.h"
#include "utils/datetime.h"
#include "utils/memutils.h"
#include "utils/ps_status.h"
+#include "utils/timeout.h"
#ifdef EXEC_BACKEND
#include "storage/spin.h"
@@ -337,6 +337,7 @@ static void reaper(SIGNAL_ARGS);
static void sigusr1_handler(SIGNAL_ARGS);
static void startup_die(SIGNAL_ARGS);
static void dummy_handler(SIGNAL_ARGS);
+static void StartupPacketTimeoutHandler(void);
static void CleanupBackend(int pid, int exitstatus);
static void HandleChildCrash(int pid, int exitstatus, const char *procname);
static void LogChildExit(int lev, const char *procname,
@@ -3415,7 +3416,7 @@ BackendInitialize(Port *port)
*/
pqsignal(SIGTERM, startup_die);
pqsignal(SIGQUIT, startup_die);
- pqsignal(SIGALRM, startup_die);
+ InitializeTimeouts(); /* establishes SIGALRM handler */
PG_SETMASK(&StartupBlockSig);
/*
@@ -3469,9 +3470,18 @@ BackendInitialize(Port *port)
* time delay, so that a broken client can't hog a connection
* indefinitely. PreAuthDelay and any DNS interactions above don't count
* against the time limit.
+ *
+ * Note: AuthenticationTimeout is applied here while waiting for the
+ * startup packet, and then again in InitPostgres for the duration of any
+ * authentication operations. So a hostile client could tie up the
+ * process for nearly twice AuthenticationTimeout before we kick him off.
+ *
+ * Note: because PostgresMain will call InitializeTimeouts again, the
+ * registration of STARTUP_PACKET_TIMEOUT will be lost. This is okay
+ * since we never use it again after this function.
*/
- if (!enable_sig_alarm(AuthenticationTimeout * 1000, false))
- elog(FATAL, "could not set timer for startup packet timeout");
+ RegisterTimeout(STARTUP_PACKET_TIMEOUT, StartupPacketTimeoutHandler);
+ enable_timeout_after(STARTUP_PACKET_TIMEOUT, AuthenticationTimeout * 1000);
/*
* Receive the startup packet (which might turn out to be a cancel request
@@ -3508,8 +3518,7 @@ BackendInitialize(Port *port)
/*
* Disable the timeout, and prevent SIGTERM/SIGQUIT again.
*/
- if (!disable_sig_alarm(false))
- elog(FATAL, "could not disable timer for startup packet timeout");
+ disable_timeout(STARTUP_PACKET_TIMEOUT, false);
PG_SETMASK(&BlockSig);
}
@@ -4311,8 +4320,8 @@ sigusr1_handler(SIGNAL_ARGS)
}
/*
- * Timeout or shutdown signal from postmaster while processing startup packet.
- * Cleanup and exit(1).
+ * SIGTERM or SIGQUIT while processing startup packet.
+ * Clean up and exit(1).
*
* XXX: possible future improvement: try to send a message indicating
* why we are disconnecting. Problem is to be sure we don't block while
@@ -4340,6 +4349,17 @@ dummy_handler(SIGNAL_ARGS)
}
/*
+ * Timeout while processing startup packet.
+ * As for startup_die(), we clean up and exit(1).
+ */
+static void
+StartupPacketTimeoutHandler(void)
+{
+ proc_exit(1);
+}
+
+
+/*
* RandomSalt
*/
static void