v1-0001-connection_hooks.patch

text/plain

Filename: v1-0001-connection_hooks.patch
Type: text/plain
Part: 0
Message: Patch proposal: New hooks in the connection path

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
Series: patch v1-0001
File+
src/backend/postmaster/postmaster.c 12 1
src/backend/utils/init/postinit.c 20 0
src/include/postmaster/postmaster.h 13 0
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index dde4bc25b1..8e00327a5d 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -567,6 +567,9 @@ int			postmaster_alive_fds[2] = {-1, -1};
 HANDLE		PostmasterHandle;
 #endif
 
+StartupPacketTimeout_hook_type StartupPacketTimeout_hook = NULL;
+BadConnPacket_hook_type BadConnPacket_hook = NULL;
+
 /*
  * Postmaster main entry point
  */
@@ -4462,8 +4465,11 @@ BackendInitialize(Port *port)
 	 * Stop here if it was bad or a cancel packet.  ProcessStartupPacket
 	 * already did any appropriate error reporting.
 	 */
-	if (status != STATUS_OK)
+	if (status != STATUS_OK) {
+		if (BadConnPacket_hook)
+			(*BadConnPacket_hook) (port);
 		proc_exit(0);
+	}
 
 	/*
 	 * Now that we have the user and database name, we can set the process
@@ -5323,6 +5329,11 @@ dummy_handler(SIGNAL_ARGS)
 static void
 StartupPacketTimeoutHandler(void)
 {
+	if (StartupPacketTimeout_hook)
+		(*StartupPacketTimeout_hook) (MyProcPort);
+	ereport(COMMERROR,
+			(errcode(ERRCODE_PROTOCOL_VIOLATION),
+			 errmsg("timeout while processing startup packet")));
 	_exit(1);
 }
 
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 6b9082604f..562ed331bf 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -67,6 +67,14 @@
 #include "utils/syscache.h"
 #include "utils/timeout.h"
 
+/*
+ * Hooks to be used when a connection has been refused in case of bad
+ * database name, bad database oid or bad permissions.
+ */
+BadDb_hook_type baddbname_hook = NULL;
+BadDb_hook_type baddboid_hook = NULL;
+BadDb_hook_type baddbperm_hook = NULL;
+
 static HeapTuple GetDatabaseTuple(const char *dbname);
 static HeapTuple GetDatabaseTupleByOid(Oid dboid);
 static void PerformAuthentication(Port *port);
@@ -360,10 +368,14 @@ CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connect
 		if (!am_superuser &&
 			pg_database_aclcheck(MyDatabaseId, GetUserId(),
 								 ACL_CONNECT) != ACLCHECK_OK)
+		{
+			if (baddbperm_hook)
+				(*baddbperm_hook) (MyProcPort);
 			ereport(FATAL,
 					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
 					 errmsg("permission denied for database \"%s\"", name),
 					 errdetail("User does not have CONNECT privilege.")));
+		}
 
 		/*
 		 * Check connection limit for this database.
@@ -918,9 +930,13 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
 
 		tuple = GetDatabaseTuple(in_dbname);
 		if (!HeapTupleIsValid(tuple))
+		{
+			if (baddbname_hook)
+				(*baddbname_hook) (MyProcPort);
 			ereport(FATAL,
 					(errcode(ERRCODE_UNDEFINED_DATABASE),
 					 errmsg("database \"%s\" does not exist", in_dbname)));
+		}
 		dbform = (Form_pg_database) GETSTRUCT(tuple);
 		MyDatabaseId = dbform->oid;
 		MyDatabaseTableSpace = dbform->dattablespace;
@@ -935,9 +951,13 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
 
 		tuple = GetDatabaseTupleByOid(dboid);
 		if (!HeapTupleIsValid(tuple))
+		{
+			if (baddboid_hook)
+				(*baddboid_hook) (MyProcPort);
 			ereport(FATAL,
 					(errcode(ERRCODE_UNDEFINED_DATABASE),
 					 errmsg("database %u does not exist", dboid)));
+		}
 		dbform = (Form_pg_database) GETSTRUCT(tuple);
 		MyDatabaseId = dbform->oid;
 		MyDatabaseTableSpace = dbform->dattablespace;
diff --git a/src/include/postmaster/postmaster.h b/src/include/postmaster/postmaster.h
index 90e333ccd2..f42c19a4d1 100644
--- a/src/include/postmaster/postmaster.h
+++ b/src/include/postmaster/postmaster.h
@@ -63,6 +63,19 @@ extern Size ShmemBackendArraySize(void);
 extern void ShmemBackendArrayAllocation(void);
 #endif
 
+/* kluge to avoid including libpq/libpq-be.h here */
+struct Port;
+typedef void (*BadDb_hook_type) (const struct Port *);
+extern PGDLLIMPORT BadDb_hook_type baddbname_hook;
+extern PGDLLIMPORT BadDb_hook_type baddboid_hook;
+extern PGDLLIMPORT BadDb_hook_type baddbperm_hook;
+
+typedef void (*BadConnPacket_hook_type) (const struct Port *);
+extern PGDLLIMPORT BadConnPacket_hook_type BadConnPacket_hook;
+
+typedef void (*StartupPacketTimeout_hook_type) (const struct Port *);
+extern PGDLLIMPORT StartupPacketTimeout_hook_type StartupPacketTimeout_hook;
+
 /*
  * Note: MAX_BACKENDS is limited to 2^18-1 because that's the width reserved
  * for buffer references in buf_internals.h.  This limitation could be lifted