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.
This commit is contained in:
Tom Lane 2007-08-04 03:15:49 +00:00
parent bdd6b62245
commit 0b9d3d4dcd

View File

@ -37,7 +37,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* *
@ -230,6 +230,7 @@ static volatile sig_atomic_t start_autovac_launcher = false;
* backend from the postmaster to that backend (via fork). * backend from the postmaster to that backend (via fork).
*/ */
static unsigned int random_seed = 0; static unsigned int random_seed = 0;
static struct timeval random_start_time;
extern char *optarg; extern char *optarg;
extern int optind, extern int optind,
@ -966,6 +967,8 @@ PostmasterMain(int argc, char *argv[])
* Remember postmaster startup time * Remember postmaster startup time
*/ */
PgStartTime = GetCurrentTimestamp(); PgStartTime = GetCurrentTimestamp();
/* PostmasterRandom wants its own copy */
gettimeofday(&random_start_time, NULL);
/* /*
* We're ready to rock and roll... * We're ready to rock and roll...
@ -1140,10 +1143,7 @@ ServerLoop(void)
int nSockets; int nSockets;
time_t now, time_t now,
last_touch_time; last_touch_time;
struct timeval earlier,
later;
gettimeofday(&earlier, NULL);
last_touch_time = time(NULL); last_touch_time = time(NULL);
nSockets = initMasks(&readmask); nSockets = initMasks(&readmask);
@ -1194,24 +1194,6 @@ ServerLoop(void)
*/ */
if (selres > 0) 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++) for (i = 0; i < MAXLISTEN; i++)
{ {
if (ListenSocket[i] == -1) if (ListenSocket[i] == -1)
@ -2970,6 +2952,7 @@ BackendRun(Port *port)
* a new random sequence in the random() library function. * a new random sequence in the random() library function.
*/ */
random_seed = 0; random_seed = 0;
random_start_time.tv_usec = 0;
/* slightly hacky way to get integer microseconds part of timestamptz */ /* slightly hacky way to get integer microseconds part of timestamptz */
TimestampDifference(0, port->SessionStartTime, &secs, &usecs); TimestampDifference(0, port->SessionStartTime, &secs, &usecs);
srandom((unsigned int) (MyProcPid ^ usecs)); srandom((unsigned int) (MyProcPid ^ usecs));
@ -3778,13 +3761,29 @@ RandomSalt(char *cryptSalt, char *md5Salt)
static long static long
PostmasterRandom(void) PostmasterRandom(void)
{ {
static bool initialized = false; /*
* Select a random seed at the time of first receiving a request.
if (!initialized) */
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); srandom(random_seed);
initialized = true;
} }
return random(); return random();