From 0b9d3d4dcd0561fbf674e09af1160f087eda535b Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sat, 4 Aug 2007 03:15:49 +0000 Subject: [PATCH] Fix a problem in my recent patch to initialize cancel_key for autovac workers as well as regular backends: if no regular backend launches before the autovac launcher tries to start an autovac worker, the postmaster would get an Assert fault due to calling PostmasterRandom before random_seed was initialized. Cleanest solution seems to be to take the initialization of random_seed out of ServerLoop and let PostmasterRandom do it for itself. --- src/backend/postmaster/postmaster.c | 53 ++++++++++++++--------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 74d90e6f88..4543c5c503 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -37,7 +37,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.538 2007/08/03 20:06:50 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.539 2007/08/04 03:15:49 tgl Exp $ * * NOTES * @@ -230,6 +230,7 @@ static volatile sig_atomic_t start_autovac_launcher = false; * backend from the postmaster to that backend (via fork). */ static unsigned int random_seed = 0; +static struct timeval random_start_time; extern char *optarg; extern int optind, @@ -966,6 +967,8 @@ PostmasterMain(int argc, char *argv[]) * Remember postmaster startup time */ PgStartTime = GetCurrentTimestamp(); + /* PostmasterRandom wants its own copy */ + gettimeofday(&random_start_time, NULL); /* * We're ready to rock and roll... @@ -1140,10 +1143,7 @@ ServerLoop(void) int nSockets; time_t now, last_touch_time; - struct timeval earlier, - later; - gettimeofday(&earlier, NULL); last_touch_time = time(NULL); nSockets = initMasks(&readmask); @@ -1194,24 +1194,6 @@ ServerLoop(void) */ if (selres > 0) { - /* - * Select a random seed at the time of first receiving a request. - */ - while (random_seed == 0) - { - gettimeofday(&later, NULL); - - /* - * We are not sure how much precision is in tv_usec, so we - * swap the high and low 16 bits of 'later' and XOR them with - * 'earlier'. On the off chance that the result is 0, we loop - * until it isn't. - */ - random_seed = earlier.tv_usec ^ - ((later.tv_usec << 16) | - ((later.tv_usec >> 16) & 0xffff)); - } - for (i = 0; i < MAXLISTEN; i++) { if (ListenSocket[i] == -1) @@ -2970,6 +2952,7 @@ BackendRun(Port *port) * a new random sequence in the random() library function. */ random_seed = 0; + random_start_time.tv_usec = 0; /* slightly hacky way to get integer microseconds part of timestamptz */ TimestampDifference(0, port->SessionStartTime, &secs, &usecs); srandom((unsigned int) (MyProcPid ^ usecs)); @@ -3778,13 +3761,29 @@ RandomSalt(char *cryptSalt, char *md5Salt) static long PostmasterRandom(void) { - static bool initialized = false; - - if (!initialized) + /* + * Select a random seed at the time of first receiving a request. + */ + if (random_seed == 0) { - Assert(random_seed != 0); + do + { + struct timeval random_stop_time; + + gettimeofday(&random_stop_time, NULL); + /* + * We are not sure how much precision is in tv_usec, so we swap + * the high and low 16 bits of 'random_stop_time' and XOR them + * with 'random_start_time'. On the off chance that the result is + * 0, we loop until it isn't. + */ + random_seed = random_start_time.tv_usec ^ + ((random_stop_time.tv_usec << 16) | + ((random_stop_time.tv_usec >> 16) & 0xffff)); + } + while (random_seed == 0); + srandom(random_seed); - initialized = true; } return random();