From 54e412efbf61fb1fef1dc9444b1bbfc13f7cabe0 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Sat, 6 Mar 2021 16:09:39 +1300
Subject: [PATCH v4 2/2] some fixups

- timer handler must set the latch
- rearm the timer from the CFI(), not the signal handler
- only rearm if we're actually still running a query (avoids wakeups
  when idle)
- just use pg_sleep() in the test instead of working harder
- SKIP_CLIENT_CHECK_TIMEOUT -> CLIENT_CONNECTION_CHECK_TIMEOUT
- a tiny doc change
---
 doc/src/sgml/config.sgml                            |  2 +-
 src/backend/libpq/pqcomm.c                          |  5 +++++
 src/backend/tcop/postgres.c                         |  8 +++++---
 src/backend/utils/init/postinit.c                   |  6 ++----
 src/include/utils/timeout.h                         |  2 +-
 .../modules/connection/t/001_close_connection.pl    | 13 +------------
 6 files changed, 15 insertions(+), 21 deletions(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index cadf6a9e7d..a8db1cc806 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -9244,7 +9244,7 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
         If the client aborts the connection, the query is terminated.
        </para>
        <para>
-        Default value is <literal>zero</literal> - it disables connection
+        Default value is <literal>zero</literal>.  Zero disables connection
         checks, so the backend will detect client disconnection only when trying
         to send a response to the query.
        </para>
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 9f33138105..bf26fda1c0 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -79,6 +79,7 @@
 #include "storage/ipc.h"
 #include "utils/guc.h"
 #include "utils/memutils.h"
+#include "utils/timeout.h"
 
 /*
  * Cope with the various platform-specific ways to spell TCP keepalive socket
@@ -1950,5 +1951,9 @@ void pq_check_client_connection(void)
 			ClientConnectionLost = true;
 			InterruptPending = true;
 		}
+
+		if (client_connection_check_interval > 0)
+			enable_timeout_after(CLIENT_CONNECTION_CHECK_TIMEOUT,
+								 client_connection_check_interval);
 	}
 }
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index c9be532362..85a2dcdd5b 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -2583,6 +2583,11 @@ start_xact_command(void)
 	 * not desired, the timeout has to be disabled explicitly.
 	 */
 	enable_statement_timeout();
+
+	/* Start timeout for checking if the client has gone away if necessary. */
+	if (client_connection_check_interval)
+		enable_timeout_after(CLIENT_CONNECTION_CHECK_TIMEOUT,
+							 client_connection_check_interval);
 }
 
 static void
@@ -4290,9 +4295,6 @@ PostgresMain(int argc, char *argv[],
 		 */
 		CHECK_FOR_INTERRUPTS();
 		DoingCommandRead = false;
-		if (client_connection_check_interval)
-			enable_timeout_after(SKIP_CLIENT_CHECK_TIMEOUT,
-								 client_connection_check_interval);
 
 		/*
 		 * (6) check for any other interesting events that happened while we
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 002b6c9fd1..2360c38bfd 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -623,7 +623,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
 		RegisterTimeout(IDLE_IN_TRANSACTION_SESSION_TIMEOUT,
 						IdleInTransactionSessionTimeoutHandler);
 		RegisterTimeout(IDLE_SESSION_TIMEOUT, IdleSessionTimeoutHandler);
-		RegisterTimeout(SKIP_CLIENT_CHECK_TIMEOUT, ClientCheckTimeoutHandler);
+		RegisterTimeout(CLIENT_CONNECTION_CHECK_TIMEOUT, ClientCheckTimeoutHandler);
 	}
 
 	/*
@@ -1251,9 +1251,7 @@ ClientCheckTimeoutHandler(void)
 {
 	CheckClientConnectionPending = true;
 	InterruptPending = true;
-	if (client_connection_check_interval > 0)
-		enable_timeout_after(SKIP_CLIENT_CHECK_TIMEOUT,
-							 client_connection_check_interval);
+	SetLatch(MyLatch);
 }
 
 /*
diff --git a/src/include/utils/timeout.h b/src/include/utils/timeout.h
index 89d94ebe18..93e6a691b3 100644
--- a/src/include/utils/timeout.h
+++ b/src/include/utils/timeout.h
@@ -32,7 +32,7 @@ typedef enum TimeoutId
 	STANDBY_LOCK_TIMEOUT,
 	IDLE_IN_TRANSACTION_SESSION_TIMEOUT,
 	IDLE_SESSION_TIMEOUT,
-	SKIP_CLIENT_CHECK_TIMEOUT,
+	CLIENT_CONNECTION_CHECK_TIMEOUT,
 	/* First user-definable timeout reason */
 	USER_TIMEOUT,
 	/* Maximum number of timeout reasons */
diff --git a/src/test/modules/connection/t/001_close_connection.pl b/src/test/modules/connection/t/001_close_connection.pl
index 7f727833ec..f688fdb666 100644
--- a/src/test/modules/connection/t/001_close_connection.pl
+++ b/src/test/modules/connection/t/001_close_connection.pl
@@ -16,18 +16,7 @@ else
 }
 
 my $long_query = q{
-DO
-$$
-DECLARE row_data RECORD;
-BEGIN
-EXECUTE 'CREATE TABLE IF NOT EXISTS keep_alive_test AS SELECT generate_series(0,100000) AS tt';
-FOR row_data IN
-    SELECT tt
-    FROM keep_alive_test
-LOOP
-    EXECUTE 'SELECT count(*) FROM keep_alive_test';
-END LOOP;
-END$$;
+SELECT pg_sleep(60);
 };
 my $set_guc_on = q{
     SET client_connection_check_interval = 1000;
-- 
2.30.1

