[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
get-internal-real-time bug
Executing this under KCL:
(dotimes (i 1000)
(time (sleep 100)))
produces the output
real time: 100.033
real time: 100.400
. . .
real time: -71482.770
real time: 100.017
real time: 100.000
. . .
real time: -71482.750
real time: 100.017
real time: 100.000
. . .
The problem is in unixtime.c:
Lget_internal_real_time()
{
#ifdef BSD
struct timeb buf;
check_arg(0);
ftime(&buf);
vs_push(make_fixnum(((buf.time-beginning.time)*1000+
(buf.millitm-beginning.millitm))*60/1000));
#endif
#ifdef ATT
....
}
The number of seconds is effectively multiplied by 60000
in the expression. This overflows a 32-bit integer
about every 9 hours. The exact behavior on overflow,
of course, depends on the machine. A simple fix is to do this:
vs_push(make_fixnum((buf.time - beginning.time) * 60 +
(buf.millitm - beginning.millitm)*60/1000));
increasing the safe period to about 400 days (but with a slightly
different rounding behavior).
However, since the variable "beginning" is initialized when
raw_kcl starts, it's still possible to catch a 400-day-old
lisp image at a bad time, but I'll save that for another bug fix.