OSDN Git Service

Fix a problem in my recent patch to initialize cancel_key for autovac workers
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 4 Aug 2007 03:15:49 +0000 (03:15 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
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 74d90e6..4543c5c 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();