[ace-bugs] ACE_Time_Value: set(double) hangs when setting large values

Johnny Willemsen jwillemsen at remedy.nl
Mon Feb 22 11:31:20 CST 2016


Hi,

Thanks for using the PRF form, we do have some pending issues with large
values to ACE_Time_Value, see
http://bugzilla.dre.vanderbilt.edu/show_bug.cgi?id=4084
http://bugzilla.dre.vanderbilt.edu/show_bug.cgi?id=2434

Can you make a pull request at https://github.com/DOCGroup/ATCD/ with
the fix and some extensions to the ACE unit tests under
ACE_wrappers/tests so that this issue is reproduced and it can't appear
back anymore.

Best regards,

Johnny Willemsen
Remedy IT
Postbus 81 | 6930 AB Westervoort | The Netherlands
http://www.remedy.nl

On 02/22/2016 05:49 PM, Markus Hossner wrote:
>     ACE VERSION: 6.3.3
> 
>     HOST MACHINE and OPERATING SYSTEM:
> Red Hat Enterprise Linux Server release 6.5 (Santiago) 64 Bit
> 
>     TARGET MACHINE and OPERATING SYSTEM, if different from HOST:
> Red Hat Enterprise Linux Server release 6.5 (Santiago) 64 Bit
> gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC)
> 
>     THE $ACE_ROOT/ace/config.h FILE
> #include "ace/config-linux.h"
> 
>     THE $ACE_ROOT/include/makeinclude/platform_macros.GNU FILE
> include $(ACE_ROOT)/include/makeinclude/platform_linux.GNU
> INSTALL_PREFIX=/usr/local/ACE+TAO-6.3.1
> LD_RPATH_FLAGS += -Wl,-rpath,/usr/local/in/lib
> 
>     CONTENTS OF $ACE_ROOT/bin/MakeProjectCreator/config/default.features
> does not exist
> 
>     AREA/CLASS/EXAMPLE AFFECTED:
> ACE_Time_Value
> 
>     DOES THE PROBLEM AFFECT:
>         EXECUTION
> 
>     SYNOPSIS:
> ACE_Time_Value: set(double) hangs when setting large values (e.g. DBL_MAX) on 64 bit platform
> 
>     DESCRIPTION:
> Through an error in our code an ACE_Time_Value was set to DBL_MAX which resulted in the program hanging in 
> ACE_Time_Value::normalize(). I looked at the code and found out that the cast from double to t_time went wrong
> which results in a very large usec value (64 bit). Then normalize() is called and normalize() uses a loop to adjust the
>  sec and usec values. For large usec values this needs very long time.
> 
> Problematic usec values can also be set directly by the constructor or a set method.
> 
>     REPEAT BY:
> In a 64 Bit environment, where suseconds_t is defined as 64 Bit value.
> 
>   cout << sizeof(suseconds_t) << endl;  // 8
>   ACE_Time_Value a(0, LONG_MAX); // hangs
> 
>   ACE_Time_Value b;
>   b.set(0, LONG_MAX); // hangs
> 
>   ACE_Time_Value c;
>   c.set(DBL_MAX); //hangs
> 
> (For repeating the problem I used extreme values but this also happens for other large numbers)
> 
> Best regards
> 
> Markus Hossner
> 
> 
>     SAMPLE FIX/WORKAROUND:
> 
> *ACE_Time_Value::set (double d)*: ace/Time_Value.inl
> - Handle big positiv and negativ double values by limiting them to possible values for sec and usec
> - Correct round for negativ double values: -10.5 => -10 -500000 (not -10 -499999)
> - no normalize needed cause result is already normalized
> 
> ACE_INLINE void
> ACE_Time_Value::set (double d)
> {
>   // ACE_OS_TRACE ("ACE_Time_Value::set");
>   if (d < ACE_Numeric_Limits<time_t>::min())
>     {
>       this->tv_.tv_sec = ACE_Numeric_Limits<time_t>::min();
>       this->tv_.tv_usec = -ACE_ONE_SECOND_IN_USECS + 1;
>     }
>   else if (d > ACE_Numeric_Limits<time_t>::max())
>     {
>       this->tv_.tv_sec = ACE_Numeric_Limits<time_t>::max();
>       this->tv_.tv_usec = ACE_ONE_SECOND_IN_USECS - 1;
>     }
>   else
>     {
>       time_t l = (time_t) d;
>       this->tv_.tv_sec = l;
>       this->tv_.tv_usec = (suseconds_t) ((d - (double) l) * ACE_ONE_SECOND_IN_USECS + (d < 0 ? -0.5 : 0.5));
>     }
> }
> 
> 
> *ACE_Time_Value::normalize (bool saturate):* ace/Time_Value.cpp
> - Better performance by not using a loop for adjusting time values
> 
> void
> ACE_Time_Value::normalize (bool saturate)
> {
>   // ACE_OS_TRACE ("ACE_Time_Value::normalize");
>   if (this->tv_.tv_usec >= ACE_ONE_SECOND_IN_USECS ||
>       this->tv_.tv_usec <= -ACE_ONE_SECOND_IN_USECS)
>     {
>       time_t sec = abs(this->tv_.tv_usec) / ACE_ONE_SECOND_IN_USECS * (this->tv_.tv_usec > 0 ? 1 : -1);
>       suseconds_t usec = this->tv_.tv_usec - sec * ACE_ONE_SECOND_IN_USECS;
> 
>       if (saturate && this->tv_.tv_sec > 0 && sec > 0 &&
>           ACE_Numeric_Limits<time_t>::max() - this->tv_.tv_sec < sec)
>         {
>           this->tv_.tv_sec = ACE_Numeric_Limits<time_t>::max();
>           this->tv_.tv_usec = ACE_ONE_SECOND_IN_USECS - 1;
>         }
>       else if (saturate && this->tv_.tv_sec < 0 && sec < 0 &&
>                ACE_Numeric_Limits<time_t>::min() - this->tv_.tv_sec > sec)
>         {
>           this->tv_.tv_sec = ACE_Numeric_Limits<time_t>::min();
>           this->tv_.tv_usec = -ACE_ONE_SECOND_IN_USECS + 1;
>         }
>       else
>         {
>           this->tv_.tv_sec += sec;
>           this->tv_.tv_usec = usec;
>         }
>     }
> 
>   if (this->tv_.tv_sec >= 1 && this->tv_.tv_usec < 0)
>     {
>       --this->tv_.tv_sec;
>       this->tv_.tv_usec += ACE_ONE_SECOND_IN_USECS;
>     }
>   // tv_sec in qnxnto is unsigned
> #if !defined ( __QNX__)
>   else if (this->tv_.tv_sec < 0 && this->tv_.tv_usec > 0)
>     {
>       ++this->tv_.tv_sec;
>       this->tv_.tv_usec -= ACE_ONE_SECOND_IN_USECS;
>     }
> #endif /* __QNX__  */
> }
> 
> 
> 
> 
> _______________________________________________
> ace-bugs mailing list
> ace-bugs at list.isis.vanderbilt.edu
> http://list.isis.vanderbilt.edu/cgi-bin/mailman/listinfo/ace-bugs
> 


More information about the ace-bugs mailing list