pkgsrc-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

pkg/46673: time/p5-Time-HiRes: "usleep( 1000000 )" does not sleep on NetBSD



>Number:         46673
>Category:       pkg
>Synopsis:       time/p5-Time-HiRes: "usleep( 1000000 )" does not sleep on 
>NetBSD
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    pkg-manager
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Jul 08 16:45:00 +0000 2012
>Originator:     Michai Ramakers
>Release:        6.0 BETA2
>Organization:
>Environment:
NetBSD main.LAN 6.0_BETA2 NetBSD 6.0_BETA2 (GENERIC) amd64
>Description:
sleeping exactly 1000000 us using Time::HiRes::usleep() incorrectly returns 
(almost) immediately, while sleeping 999999 us or 1000001 us correctly sleeps 
around 1 s.

tested on NetBSD 6.0 BETA2 amd64 with Time::HiRes 1.972101, and NetBSD 5.1 i386 
with Time::HiRes 1.9719, both expose this symptom. 


Analysis: 

From Time::HiRes 1.9724 (same version as in pkgsrc-2012Q1) 'HiRes.xs':

 785 #if defined(HAS_USLEEP) && defined(HAS_GETTIMEOFDAY)
 786 
 787 NV
 788 usleep(useconds)
 789         NV useconds
 790   PREINIT:
 791   struct timeval Ta, Tb;
 792   CODE:
 793   gettimeofday(&Ta, NULL);
 794   if (items > 0) {
 795       if (useconds > 1E6) {
 796     IV seconds = (IV) (useconds / 1E6);
 797     /* If usleep() has been implemented using setitimer()
 798      * then this contortion is unnecessary-- but usleep()
 799      * may be implemented in some other way, so let's contort. */
 800     if (seconds) {
 801         sleep(seconds);
 802         useconds -= 1E6 * seconds;
 803     }
 804       } else if (useconds < 0.0)
 805           croak("Time::HiRes::usleep(%"NVgf"): negative time not invented 
yet", useconds);
 806       usleep((U32)useconds);
 807   } else
 808       PerlProc_pause();
 809   gettimeofday(&Tb, NULL);
 810 #if 0
 811   printf("[%ld %ld] [%ld %ld]\n", Tb.tv_sec, Tb.tv_usec, Ta.tv_sec, 
Ta.tv_usec);
 812 #endif
 813   RETVAL = 1E6*(Tb.tv_sec-Ta.tv_sec)+(NV)((IV)Tb.tv_usec-(IV)Ta.tv_usec);
 814 
 815   OUTPUT:
 816   RETVAL
 817 
 818 #if defined(TIME_HIRES_NANOSLEEP)

...it seems to me  there is an off-by-one error in the check at line 795 for 
systems that provide usleep(); the check should be for greater-or-equal than, 
instead of greater-than. 

The usleep(3) on the 6.0 BETA2 system does not support sleep-times of 1M us and 
more, as per manual, and returns an error when called with 1M as argument.

Tested on a Linux system with Time::HiRes 1.9711 and an usleep(3) that accepts 
arguments including and beyond 1M us (verified using C-program) showed the 
desired behaviour for sleeping around 1 second when  argument to 
Time::HiRes::usleep is around 1M. I did not look at code of Time::HiRes 1.9711.

>How-To-Repeat:
execute from shell:

  perl -MTime::HiRes -e 'print Time::HiRes::usleep( 1000000 ) . "\n"'

Call seems to return immediately, sleeping around 3 us (as per return-value).

Changing the argument to either 999999 or 1000001 correctly sleeps around 1 
second.
>Fix:



Home | Main Index | Thread Index | Old Index