Fix syslogger to not fail when log_rotation_age exceeds 2^31 milliseconds.
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 18 Nov 2012 21:16:47 +0000 (16:16 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 18 Nov 2012 21:16:47 +0000 (16:16 -0500)
We need to avoid calling WaitLatch with timeouts exceeding INT_MAX.
Fortunately a simple clamp will do the trick, since no harm is done if
the wait times out before it's really time to rotate the log file.
Per bug #7670 (probably bug #7545 is the same thing, too).

In passing, fix bogus definition of log_rotation_age's maximum value in
guc.c --- it was numerically right, but only because MINS_PER_HOUR and
SECS_PER_MINUTE have the same value.

Back-patch to 9.2.  Before that, syslogger wasn't using WaitLatch.

src/backend/postmaster/syslogger.c
src/backend/utils/misc/guc.c

index eeba40b928a0951883838515cea1a611ef08c562..4fb9aacf6c24f1daa53097ddd803ad56f8c17601 100644 (file)
@@ -24,6 +24,7 @@
 #include "postgres.h"
 
 #include <fcntl.h>
+#include <limits.h>
 #include <signal.h>
 #include <time.h>
 #include <unistd.h>
@@ -415,11 +416,23 @@ SysLoggerMain(int argc, char *argv[])
                 * above is still close enough.  Note we can't make this calculation
                 * until after calling logfile_rotate(), since it will advance
                 * next_rotation_time.
+                *
+                * Also note that we need to beware of overflow in calculation of the
+                * timeout: with large settings of Log_RotationAge, next_rotation_time
+                * could be more than INT_MAX msec in the future.  In that case we'll
+                * wait no more than INT_MAX msec, and try again.
                 */
                if (Log_RotationAge > 0 && !rotation_disabled)
                {
-                       if (now < next_rotation_time)
-                               cur_timeout = (next_rotation_time - now) * 1000L;               /* msec */
+                       pg_time_t       delay;
+
+                       delay = next_rotation_time - now;
+                       if (delay > 0)
+                       {
+                               if (delay > INT_MAX / 1000)
+                                       delay = INT_MAX / 1000;
+                               cur_timeout = delay * 1000L;    /* msec */
+                       }
                        else
                                cur_timeout = 0;
                        cur_flags = WL_TIMEOUT;
index 9ab13475575ca799039701d0570940d43295e773..29dac8e0fe63df71221270afbd6f547224d06407 100644 (file)
@@ -2134,7 +2134,7 @@ static struct config_int ConfigureNamesInt[] =
                        GUC_UNIT_MIN
                },
                &Log_RotationAge,
-               HOURS_PER_DAY * MINS_PER_HOUR, 0, INT_MAX / MINS_PER_HOUR,
+               HOURS_PER_DAY * MINS_PER_HOUR, 0, INT_MAX / SECS_PER_MINUTE,
                NULL, NULL, NULL
        },