Fix a problem in my recent patch to initialize cancel_key for autovac workers
authorTom Lane
Sat, 4 Aug 2007 03:15:49 +0000 (03:15 +0000)
committerTom Lane
Sat, 4 Aug 2007 03:15:49 +0000 (03:15 +0000)
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

index 74d90e6f8871b302b7e3c8762b0718843d6e8bbe..4543c5c5032309bb3888c4d68cbb3127fbda3361 100644 (file)
@@ -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();