From e89fcae1267d1b508a7891df48efc8f8a48cf74e Mon Sep 17 00:00:00 2001 From: Bharath Rupireddy Date: Mon, 19 Apr 2021 19:27:53 +0530 Subject: [PATCH v1] Use a WaitLatch for Pre and Post Auth Delay Instead of using pg_usleep() for waiting PostAuthDelay and PreAuthDelay, use a WaitLatch. This has the advantage that we will realize if the postmaster has been killed since the last time we decided to sleep. --- doc/src/sgml/monitoring.sgml | 10 ++++++++++ src/backend/postmaster/autovacuum.c | 18 ++++++++++++++++-- src/backend/postmaster/bgworker.c | 8 +++++++- src/backend/postmaster/postmaster.c | 8 +++++++- src/backend/utils/activity/wait_event.c | 6 ++++++ src/backend/utils/init/postinit.c | 16 ++++++++++++++-- src/include/utils/wait_event.h | 2 ++ 7 files changed, 62 insertions(+), 6 deletions(-) diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml index 65d51ce445..22208e1b6d 100644 --- a/doc/src/sgml/monitoring.sgml +++ b/doc/src/sgml/monitoring.sgml @@ -2235,6 +2235,16 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser Waiting due to a call to pg_sleep or a sibling function. + + PostAuthDelay + Waiting on connection startup after authentication to allow attach + from a debugger. + + + PreAuthDelay + Waiting on connection startup before authentication to allow + attach from a debugger. + RecoveryApplyDelay Waiting to apply WAL during recovery because of a delay diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 83c584ddc8..f5669ef227 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -446,8 +446,15 @@ AutoVacLauncherMain(int argc, char *argv[]) ereport(DEBUG1, (errmsg_internal("autovacuum launcher started"))); + /* Apply PostAuthDelay */ if (PostAuthDelay) - pg_usleep(PostAuthDelay * 1000000L); + { + (void) WaitLatch(MyLatch, + WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH, + PostAuthDelay * 1000L, + WAIT_EVENT_POST_AUTH_DELAY); + ResetLatch(MyLatch); + } SetProcessingMode(InitProcessing); @@ -1706,8 +1713,15 @@ AutoVacWorkerMain(int argc, char *argv[]) ereport(DEBUG1, (errmsg_internal("autovacuum: processing database \"%s\"", dbname))); + /* Apply PostAuthDelay */ if (PostAuthDelay) - pg_usleep(PostAuthDelay * 1000000L); + { + (void) WaitLatch(MyLatch, + WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH, + PostAuthDelay * 1000L, + WAIT_EVENT_POST_AUTH_DELAY); + ResetLatch(MyLatch); + } /* And do an appropriate amount of work */ recentXid = ReadNextTransactionId(); diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index 11fc1b7863..3fa703c3f8 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -752,7 +752,13 @@ StartBackgroundWorker(void) /* Apply PostAuthDelay */ if (PostAuthDelay > 0) - pg_usleep(PostAuthDelay * 1000000L); + { + (void) WaitLatch(MyLatch, + WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH, + PostAuthDelay * 1000L, + WAIT_EVENT_POST_AUTH_DELAY); + ResetLatch(MyLatch); + } /* * Set up signal handlers. diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index b05db5a473..da019e6c5e 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -4313,7 +4313,13 @@ BackendInitialize(Port *port) * is not honored until after authentication.) */ if (PreAuthDelay > 0) - pg_usleep(PreAuthDelay * 1000000L); + { + (void) WaitLatch(MyLatch, + WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH, + PostAuthDelay * 1000L, + WAIT_EVENT_PRE_AUTH_DELAY); + ResetLatch(MyLatch); + } /* This flag will remain set until InitPostgres finishes authentication */ ClientAuthInProgress = true; /* limit visibility of log messages */ diff --git a/src/backend/utils/activity/wait_event.c b/src/backend/utils/activity/wait_event.c index 694cd48315..780f0cde73 100644 --- a/src/backend/utils/activity/wait_event.c +++ b/src/backend/utils/activity/wait_event.c @@ -476,6 +476,12 @@ pgstat_get_wait_timeout(WaitEventTimeout w) case WAIT_EVENT_PG_SLEEP: event_name = "PgSleep"; break; + case WAIT_EVENT_POST_AUTH_DELAY: + event_name = "PostAuthDelay"; + break; + case WAIT_EVENT_PRE_AUTH_DELAY: + event_name = "PreAuthDelay"; + break; case WAIT_EVENT_RECOVERY_APPLY_DELAY: event_name = "RecoveryApplyDelay"; break; diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 51d1bbef30..2a48fd4d5b 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -849,7 +849,13 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, /* Apply PostAuthDelay as soon as we've read all options */ if (PostAuthDelay > 0) - pg_usleep(PostAuthDelay * 1000000L); + { + (void) WaitLatch(MyLatch, + WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH, + PostAuthDelay * 1000L, + WAIT_EVENT_POST_AUTH_DELAY); + ResetLatch(MyLatch); + } /* initialize client encoding */ InitializeClientEncoding(); @@ -1055,7 +1061,13 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, /* Apply PostAuthDelay as soon as we've read all options */ if (PostAuthDelay > 0) - pg_usleep(PostAuthDelay * 1000000L); + { + (void) WaitLatch(MyLatch, + WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH, + PostAuthDelay * 1000L, + WAIT_EVENT_POST_AUTH_DELAY); + ResetLatch(MyLatch); + } /* * Initialize various default states that can't be set up until we've diff --git a/src/include/utils/wait_event.h b/src/include/utils/wait_event.h index 60b8ca76f7..024ed8cc07 100644 --- a/src/include/utils/wait_event.h +++ b/src/include/utils/wait_event.h @@ -138,6 +138,8 @@ typedef enum { WAIT_EVENT_BASE_BACKUP_THROTTLE = PG_WAIT_TIMEOUT, WAIT_EVENT_PG_SLEEP, + WAIT_EVENT_POST_AUTH_DELAY, + WAIT_EVENT_PRE_AUTH_DELAY, WAIT_EVENT_RECOVERY_APPLY_DELAY, WAIT_EVENT_RECOVERY_RETRIEVE_RETRY_INTERVAL, WAIT_EVENT_VACUUM_DELAY, -- 2.25.1