diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index a6eb0d8061..ebe8a67c0b 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -56,6 +56,10 @@ #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);