<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html>
<head>
  <meta name="Generator" content="Zarafa WebApp v7.1.11-46050">
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <title>ACE_Time_Value: set(double) hangs when setting large values</title>
</head>
<body>
<!-- begin sanitized html -->
<div class="bodyclass">
<pre>    ACE VERSION: 6.3.3

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