> > Hello, > > after a big bug hunt we also found that the implementation of the > "times" system call in uClibc 0.9.29/0.9.30 is problematic on some 32 > bits architectures (arm926 in our case); like it was reported 2 years > ago by Will. > > The fact that uClibc considers some Linux sys_times() return values as > errors makes some user space applications become crazy (Qt in our case): > when Linux "times" syscall's return value is inside uClibc errors range > (cf INTERNAL_SYSCALL_ERROR_P macro), uClibc forward a (-1) error code to > caller. An application may freeze during many seconds (40 if system tick > is 10ms), if it's event handling relies on times() accuracy. Problem > occurs after 5 minutes of system's running, when Linux tick timer value > reaches its limit on 32 bits systems.
Oh yes, been there done that :) Most arch's has this bug in linux(ppc in recent 2.6 does not). You can work around that in your app., but one should not have too: errno = 0; ret = times(NULL); /* Linux can handle NULL */ /* Workaround broken syscall impl. * A bugfix exists for the kernel, * 2.6.29 for ppc and possibly some more arch */ if (errno) ret = (unsigned long) (-errno); Not sure I like: > + /* Return value (clock_t) -1 signals an error to userspace, but if there > + wasn't any, return 0 instead. */ > + if (ret == (clock_t) -1) > + return (clock_t) 0; this will skip ahead a tick Does the patch work for times(NULL) too? Perhaps EFAULT can not be returned in this case? > > glibc has a special handling for "times" syscall. > I have attached a patch that implements times in the same way as glibc. > > Could maintainers of uClibc get inspired from that patch and do a > correction for this problem please ? > > Thanks ! > Regards, > Julien > > -- > > > > > > Implements "times" syscall like on glibc: only EFAULT is considered as a valid > error code from Linux kernel. > To handle architectures that can't distinguish the error from a return value, > make the application segfault in case of error (== bad struct tms parameter). > > Signed-off-by: Julien Boibessot <julien.boibes...@armadeus.com> > > Index: uClibc-0.9.29/libc/sysdeps/linux/common/times.c > =================================================================== > --- uClibc-0.9.29.orig/libc/sysdeps/linux/common/times.c 2010-01-27 10:15: > 38.000000000 +0100 > +++ uClibc-0.9.29/libc/sysdeps/linux/common/times.c 2010-01-27 10:49:37. > 000000000 +0100 > @@ -12,5 +12,39 @@ > > libc_hidden_proto(times) > > -_syscall1(clock_t, times, struct tms *, buf); > +clock_t times(struct tms *buf) > +{ > + INTERNAL_SYSCALL_DECL (err); > + clock_t ret = INTERNAL_SYSCALL (times, err, 1, buf); > + if (INTERNAL_SYSCALL_ERROR_P (ret, err) > + && __builtin_expect (INTERNAL_SYSCALL_ERRNO (ret, err) == EFAULT, 0)) > + { > + /* This might be an error or not. For architectures which have > + no separate return value and error indicators we cannot > + distinguish a return value of -1 from an error. Do it the > + hard way. We crash applications which pass in an invalid BUF > + pointer. */ > +#define touch(v) \ > + do { > \ > + clock_t temp = v; > \ > + asm volatile ("" : "+r" (temp)); > \ > + v = temp; > \ > + } while (0) > + touch (buf->tms_utime); > + touch (buf->tms_stime); > + touch (buf->tms_cutime); > + touch (buf->tms_cstime); > + > + /* If we come here the tms struct is valid and the kernel did not > + return an EFAULT error. Return the value given by the kernel. */ > + } > + > + /* Return value (clock_t) -1 signals an error to userspace, but if there > + wasn't any, return 0 instead. */ > + if (ret == (clock_t) -1) > + return (clock_t) 0; > + > + return ret; > +} > + > libc_hidden_def(times) > _______________________________________________ > uClibc mailing list > uClibc@uclibc.org > http://lists.busybox.net/mailman/listinfo/uclibc _______________________________________________ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc