[50 character or so descriptive subject here (for reference)]
vherva@netspan.fi
vherva@netspan.fi
Thu Apr 1 00:00:00 GMT 1999
>Submitter-Id: net
>Originator:
>Organization:
>
>Confidential: no
>Synopsis:
>Severity: serious
>Priority: medium
>Category: libc
>Class: sw-bug
>Release: libc-2.0.7
>Environment:
Host type: i686-pc-linux-gnu
System: Linux turing.netspan.fi 2.0.34 #1 Sun May 17 18:45:16 EEST 1998 i686 unknown
Architecture: i686
Addons: crypt linuxthreads localedata
Build CFLAGS: -O2 -m486 -fno-strength-reduce -g -DNDEBUG=1
Build CC: gcc -B$(common-objpfx)
Build shared: yes
Build profile: yes
Build omitfp: no
Stdio: libio
>Description:
After ~249 day uptime on an linux-2.0.34 machine the glibc-2.0.7
clock() routine begun to return -1 consistently.
The glibc-2.0.7 (and glibc-2.0.108-0.981221 - the versions are from
RedHat packages, but I doubt the function below varies all that much
across versions) seems to define clock() in
sysdeps/unix/sysv/linux/clock.c as follows:
#include <sys/times.h>
#include <time.h>
#include <unistd.h>
/* Return the time used by the program so far (user time + system time). */
clock_t
clock (void)
{
struct tms buf;
long clk_tck = __sysconf (_SC_CLK_TCK);
if (__times (&buf) < 0)
return (clock_t) -1;
return
(clk_tck <= CLOCKS_PER_SEC)
? ((unsigned long) buf.tms_utime + buf.tms_stime) * (CLOCKS_PER_SEC
/ clk_tck)
: ((unsigned long) buf.tms_utime + buf.tms_stime) / (clk_tck
/ CLOCKS_PER_SEC);
}
Since CLK_TCK = 100 and clock_t is long (32 bit signed on linux-x86) and
2^31 / CLK_TCK / 60 / 60 / 24 is 248.551348148148 days, it seemed
clear that a counter had wrapped.
A closer inspection revealed that Linux seems return an unsigned long
as the return value of sys_times:
linux-2.0.3[46]/kernel/sys.c:
asmlinkage long sys_times(struct tms * tbuf)
{
if (tbuf) {
int error = verify_area(VERIFY_WRITE,tbuf,sizeof *tbuf);
if (error)
return error;
put_user(current->utime,&tbuf->tms_utime);
put_user(current->stime,&tbuf->tms_stime);
put_user(current->cutime,&tbuf->tms_cutime);
put_user(current->cstime,&tbuf->tms_cstime);
}
return jiffies;
}
linux-2.2.1/kernel/sys.c:
asmlinkage long sys_times(struct tms * tbuf)
{
/*
* In the SMP world we might just be unlucky and have one of
* the times increment as we use it. Since the value is an
* atomically safe type this is just fine. Conceptually its
* as if the syscall took an instant longer to occur.
*/
if (tbuf)
if (copy_to_user(tbuf, ¤t->times, sizeof(struct
tms)))
return -EFAULT;
return jiffies;
}
linux-2.2.1/kernel/sched.c: unsigned long volatile jiffies=0;
linux-2.0.3[46]/kernel/sched.c: unsigned long volatile jiffies=0;
Now, glibc seems to treat this value as signed:
glibc-2.0.6:
posix/sys/times.h:extern clock_t __times __P ((struct tms *__buffer));
glibc-2.0.108-0.981221:
include/sys/times.h:extern clock_t __times __P ((struct tms *__buffer));
which makes clock() to return -1 after 248.5 days due to the
(__times() < 0) return -1; -line.
Although the real problem lies in the fact that 32 bit is not enough
for these counters, it would make more sense to me to return something
else that a consistent -1.
Hopefully, this problem will go away as our server reaches 500 day
uptime... But only for 248 days.
>How-To-Repeat:
Take a vanilla RedHat Linux 5.1 Box with vanilla linux-2.0.34 kernel
and glibc-2.0.7. Run this combination for more than 249 days non
stop. Then do
vherva@turing:/home/vherva>cat > c.c
#include <time.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
time_t i;
time_t timer = clock();
for (i = 1000000; i; i--);
printf("timer: %i\nclock(): %i\nCLK_TCK: %i\n"
"CLOCKS_PER_SEC: %i\n",
timer, clock(), CLK_TCK, CLOCKS_PER_SEC);
return 1;
}
vherva@turing:/home/vherva>gcc c.c -o c
vherva@turing:/home/vherva>time c
timer: -1
clock(): -1
CLK_TCK: 100
CLOCKS_PER_SEC: 1000000
c 0.02s user 0.00s system 418% cpu 0.005 total
Notice the 418% CPU usage on a single CPU machine.
>Fix:
Up to you.
-- v --
--
Ville Herva Ville.Herva@netspan.fi +358-50-5164500
Netspan Oy netspan@netspan.fi PL 65 FIN-02151 Espoo
http://www.netspan.fi
For my PGP key, finger vherva@netspan.fi.
More information about the Libc-alpha
mailing list