From e89fcae1267d1b508a7891df48efc8f8a48cf74e Mon Sep 17 00:00:00 2001
From: Bharath Rupireddy <bharath.rupireddy@enterprisedb.com>
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
       <entry>Waiting due to a call to <function>pg_sleep</function> or
        a sibling function.</entry>
      </row>
+     <row>
+      <entry><literal>PostAuthDelay</literal></entry>
+      <entry>Waiting on connection startup after authentication to allow attach
+      from a debugger.</entry>
+     </row>
+     <row>
+      <entry><literal>PreAuthDelay</literal></entry>
+      <entry>Waiting on connection startup before authentication to allow
+      attach from a debugger.</entry>
+     </row>
      <row>
       <entry><literal>RecoveryApplyDelay</literal></entry>
       <entry>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

