Opened 10 years ago

Closed 10 years ago

#7800 closed Bugs (duplicate)

this_thread::sleep_for for pthread environment with BOOST_THREAD_USES_CHRONO may wait repeatedly

Reported by: atara-y@… Owned by: viboes
Milestone: Component: thread
Version: Boost 1.52.0 Severity: Problem
Keywords: Cc:

Description

In 1.52 implementation for pthread environment, with BOOST_THREAD_USES_CHRONO,

  • this_thread::sleep_for(boost::chrono::seconds(n)) calls:
  • template <class Rep, class Period> void sleep_for(const chrono::duration<Rep, Period>& d) in boost/thread/v2/thread.hpp, which calls:
  • void sleep_for(const chrono::nanoseconds& ns) in boost/thread/pthread/thread_data.hpp, which calls:
            template <class Rep, class Period>
            cv_status
            wait_for(
                    unique_lock<mutex>& lock,
                    const chrono::duration<Rep, Period>& d)
            {
              using namespace chrono;
              system_clock::time_point s_now = system_clock::now();
              steady_clock::time_point c_now = steady_clock::now();
              wait_until(lock, s_now + ceil<nanoseconds>(d));
              return steady_clock::now() - c_now < d ? cv_status::no_timeout :
                                                       cv_status::timeout;
    
            }
    

in boost/thread/pthread/condition_variable_fwd.hpp. This function can return cv_status::no_timeout, even if steady_cloke::now() - c_now is nearly equal to d. At the caller side, this function is used in loop condition:

  while(cv_status::no_timeout==thread_info->sleep_condition.wait_for(lk,ns)) {}

ns is wait period and not touched in this statement. So, it tries to wait the same period again.

This behavior can be observable in FreeBSD 8.3-STABLE and Cygwin for Boost 1.52.

In trunk r82046, call graph and implementation have been changed. If BOOST_THREAD_SLEEP_FOR_IS_STEADY is defined,

  • this_thread::sleep_for(boost::chrono::seconds(n)) calls:
  • template <class Rep, class Period> void sleep_for(const chrono::duration<Rep, Period>& d) in boost/thread/v2/thread.hpp, which calls:
  • void sleep_for(const chrono::nanoseconds& ns) in boost/thread/pthread/thread_data.hpp, which calls:
  • void sleep_for(const timespec& ts) in libs/thread/src/pthread/thread.cpp, which calls:
  • bool do_wait_for(unique_lock<mutex>& lock, struct timespec const &timeout) in boost/thread/pthread/condition_variable_fwd.hpp, which calls:
  • bool do_wait_until(unique_lock<mutex>& m, struct timespec const &timeout) in boost/thread/pthread/condition_variable.hpp, which calls
  • pthread_cond_timedwait.

If pthread_cond_timedwait returns ETIMEDOUT, the following loop in void sleep_for(const timespec& ts) exits. So, there is no problem.

    while( thread_info->sleep_condition.do_wait_for(lk,ts)) {}

BOOST_HAS_NANOSLEEP is defined for both of FreeBSD and Cygwin. As a result, BOOST_THREAD_SLEEP_FOR_IS_STEADY is defined. Therefore, problems for the environment has been resolved. However, if BOOST_THREAD_SLEEP_FOR_IS_STEADY is not defined,

  • this_thread::sleep_for(boost::chrono::seconds(n)) calls:
    template <class Rep, class Period>
    void sleep_for(const chrono::duration<Rep, Period>& d)
    {
      using namespace chrono;
      if (d > duration<Rep, Period>::zero())
      {
        steady_clock::time_point c_now = steady_clock::now();
        do
        {
          sleep_until(system_clock::now() + ceil<nanoseconds>(d));
        } while (steady_clock::now() - c_now < d );
      }
    }

in boost/thread/v2/thread.hpp. The similar analysis for 1.52 can be applied on the above function. It may wait d period again.

Change History (2)

comment:1 by viboes, 10 years ago

Owner: changed from Anthony Williams to viboes
Status: newassigned
Version: Boost Development TrunkBoost 1.52.0

I guess this is a duplicate of #7665: "this_thread::sleep_for no longer uses steady_clock in thread".

Please, could you check it and confirm?

comment:2 by viboes, 10 years ago

Milestone: To Be Determined
Resolution: duplicate
Status: assignedclosed
Note: See TracTickets for help on using tickets.