From 9c18608276164868bdcc5579cf2a3cc18584ae8d Mon Sep 17 00:00:00 2001 From: Japin Date: Tue, 11 Aug 2020 10:52:14 +0800 Subject: [PATCH] Allow terminating the idle sessions --- doc/src/sgml/config.sgml | 17 +++++++++++++ src/backend/storage/lmgr/proc.c | 1 + src/backend/tcop/postgres.c | 25 +++++++++++++++++++ src/backend/utils/errcodes.txt | 1 + src/backend/utils/init/globals.c | 1 + src/backend/utils/init/postinit.c | 10 ++++++++ src/backend/utils/misc/guc.c | 11 ++++++++ src/backend/utils/misc/postgresql.conf.sample | 1 + src/include/miscadmin.h | 1 + src/include/storage/proc.h | 1 + src/include/utils/timeout.h | 1 + 11 files changed, 70 insertions(+) diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 7a7177c550..3a08fc3859 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -8185,6 +8185,23 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; + + idle_session_timeout (integer) + + idle_session_timeout configuration parameter + + + + + Terminate any session that has been idle for longer than the specified amount of time. + + + If this value is specified without units, it is taken as milliseconds. + A value of zero (the default) disables the timeout. + + + + idle_in_transaction_session_timeout (integer) diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index e57fcd2538..1903ce9557 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -60,6 +60,7 @@ int DeadlockTimeout = 1000; int StatementTimeout = 0; int LockTimeout = 0; +int IdleSessionTimeout = 0; int IdleInTransactionSessionTimeout = 0; bool log_lock_waits = false; diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index c9424f167c..15c21bc4fe 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -3204,6 +3204,16 @@ ProcessInterrupts(void) } + if (IdleSessionTimeoutPending) + { + if (IdleSessionTimeout > 0) + ereport(FATAL, + (errcode(ERRCODE_IDLE_SESSION_TIMEOUT), + errmsg("terminating connection due to idle-session timeout"))); + else + IdleSessionTimeoutPending = false; + } + if (ProcSignalBarrierPending) ProcessProcSignalBarrier(); @@ -3783,6 +3793,7 @@ PostgresMain(int argc, char *argv[], sigjmp_buf local_sigjmp_buf; volatile bool send_ready_for_query = true; bool disable_idle_in_transaction_timeout = false; + bool disable_idle_session_timeout = false; /* Initialize startup process environment if necessary. */ if (!IsUnderPostmaster) @@ -4237,6 +4248,14 @@ PostgresMain(int argc, char *argv[], set_ps_display("idle"); pgstat_report_activity(STATE_IDLE, NULL); + + /* Start the idle-session timer */ + if (IdleSessionTimeout > 0) + { + disable_idle_session_timeout = true; + enable_timeout_after(IDLE_SESSION_TIMEOUT, + IdleSessionTimeout); + } } ReadyForQuery(whereToSendOutput); @@ -4277,6 +4296,12 @@ PostgresMain(int argc, char *argv[], disable_idle_in_transaction_timeout = false; } + if (disable_idle_session_timeout) + { + disable_timeout(IDLE_SESSION_TIMEOUT, false); + disable_idle_session_timeout = false; + } + /* * (6) check for any other interesting events that happened while we * slept. diff --git a/src/backend/utils/errcodes.txt b/src/backend/utils/errcodes.txt index c79312ed03..d5935a2ca9 100644 --- a/src/backend/utils/errcodes.txt +++ b/src/backend/utils/errcodes.txt @@ -109,6 +109,7 @@ Section: Class 08 - Connection Exception 08004 E ERRCODE_SQLSERVER_REJECTED_ESTABLISHMENT_OF_SQLCONNECTION sqlserver_rejected_establishment_of_sqlconnection 08007 E ERRCODE_TRANSACTION_RESOLUTION_UNKNOWN transaction_resolution_unknown 08P01 E ERRCODE_PROTOCOL_VIOLATION protocol_violation +08008 E ERRCODE_IDLE_SESSION_TIMEOUT idle_session_timeout Section: Class 09 - Triggered Action Exception diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c index 6ab8216839..03bfd88d2c 100644 --- a/src/backend/utils/init/globals.c +++ b/src/backend/utils/init/globals.c @@ -31,6 +31,7 @@ volatile sig_atomic_t InterruptPending = false; volatile sig_atomic_t QueryCancelPending = false; volatile sig_atomic_t ProcDiePending = false; volatile sig_atomic_t ClientConnectionLost = false; +volatile sig_atomic_t IdleSessionTimeoutPending = false; volatile sig_atomic_t IdleInTransactionSessionTimeoutPending = false; volatile sig_atomic_t ProcSignalBarrierPending = false; volatile uint32 InterruptHoldoffCount = 0; diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index f4247ea70d..6644545727 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -72,6 +72,7 @@ static void InitCommunication(void); static void ShutdownPostgres(int code, Datum arg); static void StatementTimeoutHandler(void); static void LockTimeoutHandler(void); +static void IdleSessionTimeoutHandler(void); static void IdleInTransactionSessionTimeoutHandler(void); static bool ThereIsAtLeastOneRole(void); static void process_startup_options(Port *port, bool am_superuser); @@ -629,6 +630,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, RegisterTimeout(DEADLOCK_TIMEOUT, CheckDeadLockAlert); RegisterTimeout(STATEMENT_TIMEOUT, StatementTimeoutHandler); RegisterTimeout(LOCK_TIMEOUT, LockTimeoutHandler); + RegisterTimeout(IDLE_SESSION_TIMEOUT, IdleSessionTimeoutHandler); RegisterTimeout(IDLE_IN_TRANSACTION_SESSION_TIMEOUT, IdleInTransactionSessionTimeoutHandler); } @@ -1233,6 +1235,14 @@ LockTimeoutHandler(void) kill(MyProcPid, SIGINT); } +static void +IdleSessionTimeoutHandler(void) +{ + IdleSessionTimeoutPending = true; + InterruptPending = true; + SetLatch(MyLatch); +} + static void IdleInTransactionSessionTimeoutHandler(void) { diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index de87ad6ef7..cd81177c4f 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -2503,6 +2503,17 @@ static struct config_int ConfigureNamesInt[] = NULL, NULL, NULL }, + { + {"idle_session_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT, + gettext_noop("Sets the maximum allowed duration of any idling session."), + gettext_noop("A value of 0 turns off the timeout."), + GUC_UNIT_MS + }, + &IdleSessionTimeout, + 0, 0, INT_MAX, + NULL, NULL, NULL + }, + { {"idle_in_transaction_session_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT, gettext_noop("Sets the maximum allowed duration of any idling transaction."), diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index 9cb571f7cc..6e3f14f234 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -664,6 +664,7 @@ #statement_timeout = 0 # in milliseconds, 0 is disabled #lock_timeout = 0 # in milliseconds, 0 is disabled #idle_in_transaction_session_timeout = 0 # in milliseconds, 0 is disabled +#idle_session_timeout = 0 # in milliseconds, 0 is disabled #vacuum_freeze_min_age = 50000000 #vacuum_freeze_table_age = 150000000 #vacuum_multixact_freeze_min_age = 5000000 diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 72e3352398..995b603899 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -81,6 +81,7 @@ extern PGDLLIMPORT volatile sig_atomic_t InterruptPending; extern PGDLLIMPORT volatile sig_atomic_t QueryCancelPending; extern PGDLLIMPORT volatile sig_atomic_t ProcDiePending; +extern PGDLLIMPORT volatile sig_atomic_t IdleSessionTimeoutPending; extern PGDLLIMPORT volatile sig_atomic_t IdleInTransactionSessionTimeoutPending; extern PGDLLIMPORT volatile sig_atomic_t ProcSignalBarrierPending; diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h index 5ceb2494ba..cb4f76d3f3 100644 --- a/src/include/storage/proc.h +++ b/src/include/storage/proc.h @@ -299,6 +299,7 @@ extern PGPROC *PreparedXactProcs; extern PGDLLIMPORT int DeadlockTimeout; extern PGDLLIMPORT int StatementTimeout; extern PGDLLIMPORT int LockTimeout; +extern PGDLLIMPORT int IdleSessionTimeout; extern PGDLLIMPORT int IdleInTransactionSessionTimeout; extern bool log_lock_waits; diff --git a/src/include/utils/timeout.h b/src/include/utils/timeout.h index 83a15f6795..6be398c983 100644 --- a/src/include/utils/timeout.h +++ b/src/include/utils/timeout.h @@ -30,6 +30,7 @@ typedef enum TimeoutId STANDBY_DEADLOCK_TIMEOUT, STANDBY_TIMEOUT, STANDBY_LOCK_TIMEOUT, + IDLE_SESSION_TIMEOUT, IDLE_IN_TRANSACTION_SESSION_TIMEOUT, /* First user-definable timeout reason */ USER_TIMEOUT, -- 2.27.0