From 921c474e2c117535392b1287454bb44e9c550afb Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Tue, 9 Oct 2018 14:32:47 +1300 Subject: [PATCH] Make sure we initialize random seeds per backend. Background workers, including parallel workers, were generating the same sequence of numbers in various code paths that use random(). The case noticed as DSM handle generation, where many collisions can occur during Parallal Hash execution, but there are probably other ways to see this. Repair by refactoring the seed initialization code such that all backends run it. Use the same function for the postmaster, its children and also standalone processes, for consistency. Author: Thomas Munro Reviewed-by: Tom Lane Discussion: https://postgr.es/m/CAEepm%3D2eJj_6%3DB%2B2tEpGu2nf1BjthCf9nXXUouYvJJ4C5WSwhg%40mail.gmail.com --- src/backend/postmaster/postmaster.c | 43 +++++++++++++++++------------ src/backend/utils/init/miscinit.c | 4 ++- src/include/postmaster/postmaster.h | 1 + 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 41de140ae01..9e90306f411 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -602,10 +602,10 @@ PostmasterMain(int argc, char *argv[]) * * Note: the seed is pretty predictable from externally-visible facts such * as postmaster start time, so avoid using random() for security-critical - * random values during postmaster startup. At the time of first - * connection, PostmasterRandom will select a hopefully-more-random seed. + * random values during postmaster startup. InitPostmasterChild() will + * do this again to set a new seed in child processes. */ - srandom((unsigned int) (MyProcPid ^ MyStartTime)); + InitRandomSeeds(); /* * By default, palloc() requests in the postmaster will be allocated in @@ -2513,6 +2513,28 @@ ClosePostmasterPorts(bool am_syslogger) } +/* + * InitRandomSeeds -- initialize seeds for random number generators + * + * Called in every backend after MyProcPid and MyStartTime have been assigned. + */ +void +InitRandomSeeds(void) +{ + /* + * Don't want backend to be able to see the postmaster random number + * generator state. We have to clobber the static random_seed. + */ +#ifndef HAVE_STRONG_RANDOM + random_seed = 0; + random_start_time.tv_usec = 0; +#endif + + /* Set a different seed for random() in every backend. */ + srandom((unsigned int) (MyProcPid ^ MyStartTime)); +} + + /* * reset_shared -- reset shared memory and semaphores */ @@ -4315,23 +4337,8 @@ BackendRun(Port *port) char **av; int maxac; int ac; - long secs; - int usecs; int i; - /* - * Don't want backend to be able to see the postmaster random number - * generator state. We have to clobber the static random_seed *and* start - * a new random sequence in the random() library function. - */ -#ifndef HAVE_STRONG_RANDOM - random_seed = 0; - random_start_time.tv_usec = 0; -#endif - /* slightly hacky way to convert timestamptz into integers */ - TimestampDifference(0, port->SessionStartTime, &secs, &usecs); - srandom((unsigned int) (MyProcPid ^ (usecs << 12) ^ secs)); - /* * Now, build the argv vector that will be given to PostgresMain. * diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index f590ecb25e8..f35bfe813f9 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -278,6 +278,8 @@ InitPostmasterChild(void) MyStartTime = time(NULL); /* set our start time in case we call elog */ + InitRandomSeeds(); /* set up per-backend random seeds */ + /* * make sure stderr is in binary mode before anything can possibly be * written to it, in case it's actually the syslogger pipe, so the pipe @@ -331,7 +333,7 @@ InitStandaloneProcess(const char *argv0) * high-entropy seed before any user query. Fewer distinct initial seeds * can occur here. */ - srandom((unsigned int) (MyProcPid ^ MyStartTime)); + InitRandomSeeds(); /* Initialize process-local latch support */ InitializeLatchSupport(); diff --git a/src/include/postmaster/postmaster.h b/src/include/postmaster/postmaster.h index 1877eef2391..217ef4490f4 100644 --- a/src/include/postmaster/postmaster.h +++ b/src/include/postmaster/postmaster.h @@ -48,6 +48,7 @@ extern PGDLLIMPORT const char *progname; extern void PostmasterMain(int argc, char *argv[]) pg_attribute_noreturn(); extern void ClosePostmasterPorts(bool am_syslogger); +extern void InitRandomSeeds(void); extern int MaxLivePostmasterChildren(void); -- 2.17.1 (Apple Git-112)