From a3f9d75237c14326cc0f96506f26f887d142e633 Mon Sep 17 00:00:00 2001
From: Nathan Bossart <bossartn@amazon.com>
Date: Thu, 10 Jun 2021 03:00:49 +0000
Subject: [PATCH v1 1/1] add pg_ctl option for retreiving shmem size

---
 src/backend/postmaster/postmaster.c | 31 ++++++++++++++++++++++++-------
 src/backend/storage/ipc/ipci.c      |  9 +++++++--
 src/backend/tcop/postgres.c         |  6 +++++-
 src/backend/utils/init/postinit.c   |  2 +-
 src/bin/pg_ctl/pg_ctl.c             | 23 ++++++++++++++++++++++-
 src/include/storage/ipc.h           |  2 +-
 6 files changed, 60 insertions(+), 13 deletions(-)

diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 5a050898fe..b2fc67f4a2 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -586,6 +586,7 @@ PostmasterMain(int argc, char *argv[])
 	bool		listen_addr_saved = false;
 	int			i;
 	char	   *output_config_variable = NULL;
+	bool		output_shmem = false;
 
 	InitProcessGlobals();
 
@@ -702,7 +703,7 @@ PostmasterMain(int argc, char *argv[])
 	 * tcop/postgres.c (the option sets should not conflict) and with the
 	 * common help() function in main/main.c.
 	 */
-	while ((opt = getopt(argc, argv, "B:bc:C:D:d:EeFf:h:ijk:lN:nOPp:r:S:sTt:W:-:")) != -1)
+	while ((opt = getopt(argc, argv, "B:bc:C:D:d:EeFf:h:ijk:lMN:nOPp:r:S:sTt:W:-:")) != -1)
 	{
 		switch (opt)
 		{
@@ -768,6 +769,10 @@ PostmasterMain(int argc, char *argv[])
 				SetConfigOption("ssl", "true", PGC_POSTMASTER, PGC_S_ARGV);
 				break;
 
+			case 'M':
+				output_shmem = true;
+				break;
+
 			case 'N':
 				SetConfigOption("max_connections", optarg, PGC_POSTMASTER, PGC_S_ARGV);
 				break;
@@ -1019,6 +1024,18 @@ PostmasterMain(int argc, char *argv[])
 	 */
 	InitializeMaxBackends();
 
+	if (output_shmem)
+	{
+		char output[64];
+		Size size;
+
+		size = CreateSharedMemoryAndSemaphores(true);
+		sprintf(output, "%zu", size);
+
+		puts(output);
+		ExitPostmaster(0);
+	}
+
 	/*
 	 * Set up shared memory and semaphores.
 	 */
@@ -2660,7 +2677,7 @@ reset_shared(void)
 	 * (if using SysV shmem and/or semas).  This helps ensure that we will
 	 * clean up dead IPC objects if the postmaster crashes and is restarted.
 	 */
-	CreateSharedMemoryAndSemaphores();
+	(void) CreateSharedMemoryAndSemaphores(false);
 }
 
 
@@ -5014,7 +5031,7 @@ SubPostmasterMain(int argc, char *argv[])
 		InitProcess();
 
 		/* Attach process to shared data structures */
-		CreateSharedMemoryAndSemaphores();
+		(void) CreateSharedMemoryAndSemaphores(false);
 
 		/* And run the backend */
 		BackendRun(&port);		/* does not return */
@@ -5028,7 +5045,7 @@ SubPostmasterMain(int argc, char *argv[])
 		InitAuxiliaryProcess();
 
 		/* Attach process to shared data structures */
-		CreateSharedMemoryAndSemaphores();
+		(void) CreateSharedMemoryAndSemaphores(false);
 
 		AuxiliaryProcessMain(argc - 2, argv + 2);	/* does not return */
 	}
@@ -5041,7 +5058,7 @@ SubPostmasterMain(int argc, char *argv[])
 		InitProcess();
 
 		/* Attach process to shared data structures */
-		CreateSharedMemoryAndSemaphores();
+		(void) CreateSharedMemoryAndSemaphores(false);
 
 		AutoVacLauncherMain(argc - 2, argv + 2);	/* does not return */
 	}
@@ -5054,7 +5071,7 @@ SubPostmasterMain(int argc, char *argv[])
 		InitProcess();
 
 		/* Attach process to shared data structures */
-		CreateSharedMemoryAndSemaphores();
+		(void) CreateSharedMemoryAndSemaphores(false);
 
 		AutoVacWorkerMain(argc - 2, argv + 2);	/* does not return */
 	}
@@ -5072,7 +5089,7 @@ SubPostmasterMain(int argc, char *argv[])
 		InitProcess();
 
 		/* Attach process to shared data structures */
-		CreateSharedMemoryAndSemaphores();
+		(void) CreateSharedMemoryAndSemaphores(false);
 
 		/* Fetch MyBgworkerEntry from shared memory */
 		shmem_slot = atoi(argv[1] + 15);
diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c
index 3e4ec53a97..0202e59748 100644
--- a/src/backend/storage/ipc/ipci.c
+++ b/src/backend/storage/ipc/ipci.c
@@ -91,8 +91,8 @@ RequestAddinShmemSpace(Size size)
  * check IsUnderPostmaster, rather than EXEC_BACKEND, to detect this case.
  * This is a bit code-wasteful and could be cleaned up.)
  */
-void
-CreateSharedMemoryAndSemaphores(void)
+Size
+CreateSharedMemoryAndSemaphores(bool size_only)
 {
 	PGShmemHeader *shim = NULL;
 
@@ -161,6 +161,9 @@ CreateSharedMemoryAndSemaphores(void)
 		/* might as well round it off to a multiple of a typical page size */
 		size = add_size(size, 8192 - (size % 8192));
 
+		if (size_only)
+			return size;
+
 		elog(DEBUG3, "invoking IpcMemoryCreate(size=%zu)", size);
 
 		/*
@@ -288,4 +291,6 @@ CreateSharedMemoryAndSemaphores(void)
 	 */
 	if (shmem_startup_hook)
 		shmem_startup_hook();
+
+	return 0;
 }
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 8cea10c901..1ef3fdf8d1 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3711,7 +3711,7 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx,
 	 * postmaster/postmaster.c (the option sets should not conflict) and with
 	 * the common help() function in main/main.c.
 	 */
-	while ((flag = getopt(argc, argv, "B:bc:C:D:d:EeFf:h:ijk:lN:nOPp:r:S:sTt:v:W:-:")) != -1)
+	while ((flag = getopt(argc, argv, "B:bc:C:D:d:EeFf:h:ijk:lMN:nOPp:r:S:sTt:v:W:-:")) != -1)
 	{
 		switch (flag)
 		{
@@ -3777,6 +3777,10 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx,
 				SetConfigOption("ssl", "true", ctx, gucsource);
 				break;
 
+			case 'M':
+				/* ignored for consistency with postmaster */
+				break;
+
 			case 'N':
 				SetConfigOption("max_connections", optarg, ctx, gucsource);
 				break;
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 51d1bbef30..7c329009d2 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -437,7 +437,7 @@ InitCommunication(void)
 		 * We're running a postgres bootstrap process or a standalone backend,
 		 * so we need to set up shmem.
 		 */
-		CreateSharedMemoryAndSemaphores();
+		(void) CreateSharedMemoryAndSemaphores(false);
 	}
 }
 
diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c
index 7985da0a94..9678185930 100644
--- a/src/bin/pg_ctl/pg_ctl.c
+++ b/src/bin/pg_ctl/pg_ctl.c
@@ -67,7 +67,8 @@ typedef enum
 	KILL_COMMAND,
 	REGISTER_COMMAND,
 	UNREGISTER_COMMAND,
-	RUN_AS_SERVICE_COMMAND
+	RUN_AS_SERVICE_COMMAND,
+	OUTPUT_SHARED_MEMORY_COMMAND
 } CtlCommand;
 
 #define DEFAULT_WAIT	60
@@ -898,6 +899,9 @@ do_start(void)
 
 	pm_pid = start_postmaster();
 
+	if (ctl_command == OUTPUT_SHARED_MEMORY_COMMAND)
+		return;
+
 	if (do_wait)
 	{
 		/*
@@ -2469,6 +2473,20 @@ main(int argc, char **argv)
 			else if (strcmp(argv[optind], "runservice") == 0)
 				ctl_command = RUN_AS_SERVICE_COMMAND;
 #endif
+			else if (strcmp(argv[optind], "output_shared_memory") == 0)
+			{
+				ctl_command = OUTPUT_SHARED_MEMORY_COMMAND;
+
+				if (!post_opts)
+					post_opts = pstrdup("-M");
+				else
+				{
+					char *old_post_opts = post_opts;
+
+					post_opts = psprintf("%s %s", old_post_opts, "-M");
+					free(old_post_opts);
+				}
+			}
 			else
 			{
 				write_stderr(_("%s: unrecognized operation mode \"%s\"\n"), progname, argv[optind]);
@@ -2572,6 +2590,9 @@ main(int argc, char **argv)
 			pgwin32_doRunAsService();
 			break;
 #endif
+		case OUTPUT_SHARED_MEMORY_COMMAND:
+			do_start();
+			break;
 		default:
 			break;
 	}
diff --git a/src/include/storage/ipc.h b/src/include/storage/ipc.h
index 753a6dd4d7..cdb1dd266d 100644
--- a/src/include/storage/ipc.h
+++ b/src/include/storage/ipc.h
@@ -77,6 +77,6 @@ extern void check_on_shmem_exit_lists_are_empty(void);
 /* ipci.c */
 extern PGDLLIMPORT shmem_startup_hook_type shmem_startup_hook;
 
-extern void CreateSharedMemoryAndSemaphores(void);
+extern Size CreateSharedMemoryAndSemaphores(bool size_only);
 
 #endif							/* IPC_H */
-- 
2.16.6

