From 21bf5544be95f638f5ccb25dfb6332e6ddb0013b Mon Sep 17 00:00:00 2001 From: Bharath Rupireddy Date: Tue, 27 Jul 2021 05:13:52 +0000 Subject: [PATCH v3] Use a WaitLatch for {pre, 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. For PostAuthDelay, don't use WL_LATCH_SET. Because MyLatch, on which WaitLatch is going to wait, could have been set in SwitchToSharedLatch() by InitProcess(). For PreAuthDelay, although there is no problem to use WL_LATCH_SET as MyLatch still points to local latch in BackendInitialize() and isn't fully initialized for the backend. For this reason and to be consistent with PostAuthDelay let's not use WL_LATCH_SET for PreAuthDelay. --- doc/src/sgml/monitoring.sgml | 10 ++++++++++ src/backend/postmaster/autovacuum.c | 24 ++++++++++++++++++++++-- src/backend/postmaster/bgworker.c | 11 ++++++++++- src/backend/postmaster/postmaster.c | 11 ++++++++++- src/backend/utils/activity/wait_event.c | 6 ++++++ src/backend/utils/init/postinit.c | 22 ++++++++++++++++++++-- src/include/utils/wait_event.h | 2 ++ 7 files changed, 80 insertions(+), 6 deletions(-) diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml index 74a58a916c..b0d5d75d09 100644 --- a/doc/src/sgml/monitoring.sgml +++ b/doc/src/sgml/monitoring.sgml @@ -2228,6 +2228,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 + attaching a debugger to the process. + + + PreAuthDelay + Waiting on connection startup before authentication to allow + attaching a debugger to the process. + 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 912ef9cb54..2712c48c56 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -446,8 +446,18 @@ AutoVacLauncherMain(int argc, char *argv[]) ereport(DEBUG1, (errmsg_internal("autovacuum launcher started"))); + /* Apply PostAuthDelay */ if (PostAuthDelay) - pg_usleep(PostAuthDelay * 1000000L); + { + /* + * If WL_LATCH_SET is used, PostAuthDelay may not be applied, since + * MyLatch might already be set. + */ + (void) WaitLatch(MyLatch, + WL_TIMEOUT | WL_EXIT_ON_PM_DEATH, + PostAuthDelay * 1000L, + WAIT_EVENT_POST_AUTH_DELAY); + } SetProcessingMode(InitProcessing); @@ -1706,8 +1716,18 @@ AutoVacWorkerMain(int argc, char *argv[]) ereport(DEBUG1, (errmsg_internal("autovacuum: processing database \"%s\"", dbname))); + /* Apply PostAuthDelay */ if (PostAuthDelay) - pg_usleep(PostAuthDelay * 1000000L); + { + /* + * If WL_LATCH_SET is used, PostAuthDelay may not be applied, + * since MyLatch might already be set. + */ + (void) WaitLatch(MyLatch, + WL_TIMEOUT | WL_EXIT_ON_PM_DEATH, + PostAuthDelay * 1000L, + WAIT_EVENT_POST_AUTH_DELAY); + } /* And do an appropriate amount of work */ recentXid = ReadNextTransactionId(); diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index c40410d73e..d605381c83 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -763,7 +763,16 @@ StartBackgroundWorker(void) /* Apply PostAuthDelay */ if (PostAuthDelay > 0) - pg_usleep(PostAuthDelay * 1000000L); + { + /* + * If WL_LATCH_SET is used, PostAuthDelay may not be applied, since + * MyLatch might already be set. + */ + (void) WaitLatch(MyLatch, + WL_TIMEOUT | WL_EXIT_ON_PM_DEATH, + PostAuthDelay * 1000L, + WAIT_EVENT_POST_AUTH_DELAY); + } /* * Set up signal handlers. diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 122c2b05bd..432c9bc478 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -4331,7 +4331,16 @@ BackendInitialize(Port *port) * is not honored until after authentication.) */ if (PreAuthDelay > 0) - pg_usleep(PreAuthDelay * 1000000L); + { + /* + * WL_LATCH_SET is not used for consistency with PostAuthDelay. MyLatch + * isn't fully initialized for the backend at this point, anyway. + */ + (void) WaitLatch(MyLatch, + WL_TIMEOUT | WL_EXIT_ON_PM_DEATH, + PreAuthDelay * 1000L, + WAIT_EVENT_PRE_AUTH_DELAY); + } /* 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 ef7e6bfb77..9b2835bef8 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..e8362bdd7c 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -849,7 +849,16 @@ 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); + { + /* + * If WL_LATCH_SET is used, PostAuthDelay may not be applied, + * since MyLatch might already be set. + */ + (void) WaitLatch(MyLatch, + WL_TIMEOUT | WL_EXIT_ON_PM_DEATH, + PostAuthDelay * 1000L, + WAIT_EVENT_POST_AUTH_DELAY); + } /* initialize client encoding */ InitializeClientEncoding(); @@ -1055,7 +1064,16 @@ 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); + { + /* + * If WL_LATCH_SET is used, PostAuthDelay may not be applied, since + * MyLatch might already be set. + */ + (void) WaitLatch(MyLatch, + WL_TIMEOUT | WL_EXIT_ON_PM_DEATH, + PostAuthDelay * 1000L, + WAIT_EVENT_POST_AUTH_DELAY); + } /* * 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 6007827b44..1154f537b3 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