mirror of
https://github.com/postgres/postgres.git
synced 2025-07-05 07:21:24 +03:00
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
This commit is contained in:
@ -41,7 +41,6 @@
|
||||
#include "storage/fd.h"
|
||||
#include "storage/ipc.h"
|
||||
#include "storage/lmgr.h"
|
||||
#include "storage/proc.h"
|
||||
#include "storage/procarray.h"
|
||||
#include "storage/procsignal.h"
|
||||
#include "storage/proc.h"
|
||||
@ -56,6 +55,7 @@
|
||||
#include "utils/ps_status.h"
|
||||
#include "utils/snapmgr.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/timeout.h"
|
||||
#include "utils/tqual.h"
|
||||
|
||||
|
||||
@ -65,6 +65,7 @@ static void PerformAuthentication(Port *port);
|
||||
static void CheckMyDatabase(const char *name, bool am_superuser);
|
||||
static void InitCommunication(void);
|
||||
static void ShutdownPostgres(int code, Datum arg);
|
||||
static void StatementTimeoutHandler(void);
|
||||
static bool ThereIsAtLeastOneRole(void);
|
||||
static void process_startup_options(Port *port, bool am_superuser);
|
||||
static void process_settings(Oid databaseid, Oid roleid);
|
||||
@ -205,8 +206,7 @@ PerformAuthentication(Port *port)
|
||||
* during authentication. Since we're inside a transaction and might do
|
||||
* database access, we have to use the statement_timeout infrastructure.
|
||||
*/
|
||||
if (!enable_sig_alarm(AuthenticationTimeout * 1000, true))
|
||||
elog(FATAL, "could not set timer for authorization timeout");
|
||||
enable_timeout_after(STATEMENT_TIMEOUT, AuthenticationTimeout * 1000);
|
||||
|
||||
/*
|
||||
* Now perform authentication exchange.
|
||||
@ -216,8 +216,7 @@ PerformAuthentication(Port *port)
|
||||
/*
|
||||
* Done with authentication. Disable the timeout, and log if needed.
|
||||
*/
|
||||
if (!disable_sig_alarm(true))
|
||||
elog(FATAL, "could not disable timer for authorization timeout");
|
||||
disable_timeout(STATEMENT_TIMEOUT, false);
|
||||
|
||||
if (Log_connections)
|
||||
{
|
||||
@ -495,6 +494,16 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
|
||||
/* Now that we have a BackendId, we can participate in ProcSignal */
|
||||
ProcSignalInit(MyBackendId);
|
||||
|
||||
/*
|
||||
* Also set up timeout handlers needed for backend operation. We need
|
||||
* these in every case except bootstrap.
|
||||
*/
|
||||
if (!bootstrap)
|
||||
{
|
||||
RegisterTimeout(DEADLOCK_TIMEOUT, CheckDeadLock);
|
||||
RegisterTimeout(STATEMENT_TIMEOUT, StatementTimeoutHandler);
|
||||
}
|
||||
|
||||
/*
|
||||
* bufmgr needs another initialization call too
|
||||
*/
|
||||
@ -974,6 +983,20 @@ ShutdownPostgres(int code, Datum arg)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* STATEMENT_TIMEOUT handler: trigger a query-cancel interrupt.
|
||||
*/
|
||||
static void
|
||||
StatementTimeoutHandler(void)
|
||||
{
|
||||
#ifdef HAVE_SETSID
|
||||
/* try to signal whole process group */
|
||||
kill(-MyProcPid, SIGINT);
|
||||
#endif
|
||||
kill(MyProcPid, SIGINT);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Returns true if at least one role is defined in this database cluster.
|
||||
*/
|
||||
|
Reference in New Issue
Block a user