initdb: Select working dynamic shared memory implementation.
authorRobert Haas
Thu, 10 Oct 2013 23:38:56 +0000 (19:38 -0400)
committerRobert Haas
Thu, 10 Oct 2013 23:46:31 +0000 (19:46 -0400)
If POSIX shared memory is supported and works, we prefer it.
Otherwise, we prefer System V, except on Windows, where we use
the implementation specific to that platform.

src/bin/initdb/initdb.c

index a6eb0d806162b0665acd1b58ca440bfa6d35c0c0..ebe8a67c0b548f89d7a0abda2e4b2f56112610ce 100644 (file)
 #include 
 #include 
 
+#ifdef HAVE_SHM_OPEN
+#include "sys/mman.h"
+#endif
+
 #include "mb/pg_wchar.h"
 #include "getaddrinfo.h"
 #include "getopt_long.h"
@@ -150,6 +154,7 @@ static char *pgdata_native;
 /* defaults */
 static int n_connections = 10;
 static int n_buffers = 50;
+static char *dynamic_shared_memory_type = NULL;
 
 /*
  * Warning messages for authentication methods
@@ -1076,6 +1081,50 @@ set_null_conf(void)
    free(path);
 }
 
+/*
+ * Determine which dynamic shared memory implementation should be used on
+ * this platform.  POSIX shared memory is preferable because the default
+ * allocation limits are much higher than the limits for System V on most
+ * systems that support both, but the fact that a platform has shm_open
+ * doesn't guarantee that that call will succeed when attempted.  So, we
+ * attempt to reproduce what the postmaster will do when allocating a POSIX
+ * segment in dsm_impl.c; if it doesn't work, we assume it won't work for
+ * the postmaster either, and configure the cluster for System V shared
+ * memory instead.
+ */
+static char *
+choose_dsm_implementation(void)
+{
+#ifdef HAVE_SHM_OPEN
+   int     ntries = 10;
+
+   while (ntries > 0)
+   {
+       uint32  handle;
+       char    name[64];
+       int     fd;
+
+       handle = random();
+       snprintf(name, 64, "/PostgreSQL.%u", handle);
+       if ((fd = shm_open(name, O_CREAT | O_RDWR | O_EXCL, 0600)) != -1)
+       {
+           close(fd);
+           shm_unlink(name);
+           return "posix";
+       }
+       if (errno != EEXIST)
+           break;
+       --ntries;
+   }
+#endif
+
+#ifdef WIN32
+   return "windows";
+#else
+   return "sysv";
+#endif
+}
+
 /*
  * Determine platform-specific config settings
  *
@@ -1157,6 +1206,7 @@ test_config_settings(void)
                 SYSTEMQUOTE "\"%s\" --boot -x0 %s "
                 "-c max_connections=%d "
                 "-c shared_buffers=%d "
+                "-c dynamic_shared_memory_type=none "
                 "< \"%s\" > \"%s\" 2>&1" SYSTEMQUOTE,
                 backend_exec, boot_options,
                 n_connections, test_buffs,
@@ -1171,6 +1221,11 @@ test_config_settings(void)
        printf("%dMB\n", (n_buffers * (BLCKSZ / 1024)) / 1024);
    else
        printf("%dkB\n", n_buffers * (BLCKSZ / 1024));
+
+   printf(_("selecting dynamic shared memory implementation ... "));
+   fflush(stdout);
+   dynamic_shared_memory_type = choose_dsm_implementation();
+   printf("%s\n", dynamic_shared_memory_type);
 }
 
 /*
@@ -1265,6 +1320,11 @@ setup_config(void)
        conflines = replace_token(conflines, "#log_timezone = 'GMT'", repltok);
    }
 
+   snprintf(repltok, sizeof(repltok), "dynamic_shared_memory_type = %s",
+            dynamic_shared_memory_type);
+   conflines = replace_token(conflines, "#dynamic_shared_memory_type = posix",
+                             repltok);
+
    snprintf(path, sizeof(path), "%s/postgresql.conf", pg_data);
 
    writefile(path, conflines);