[ace-users] ACE Library Bug: ACE_Thread_Timer_Queue_Adapter has a Time Policy Issue
Johnny Willemsen
jwillemsen at remedy.nl
Tue Feb 19 06:47:15 CST 2019
Hi,
Thanks for using the PRF form. We discussed your issue this morning
within our Remedy IT support team. During the discussion we identified a
much easier and smaller solution which we implemented and tested. See
https://github.com/DOCGroup/ACE_TAO/pull/837 for the pull request we
prepared and merged to ACE/TAO master, this change will be part of the
next ACE release.
Johnny Willemsen
Remedy IT
http://www.remedy.nl
On 2/19/19 3:33 AM, Wanner, Charles W [US] (AS) wrote:
>
> Version: ACE+TAO 6.4.5
>
>
>
> HOST: CentOS Linux release 7.6.1810 (Core)
>
>
>
> Config.h Contents:
>
> #define ACE_ENABLE_SWAP_ON_WRITE
>
> #define ACE_LACKS_CDR_ALIGNMENT
>
> #define ACE_HAS_CLOCK_GETTIME_MONOTONIC
>
> #define ACE_HAS_IPV6
>
> #define ACE_USES_IPV4_IPV6_MIGRATION
>
> #include "ace/config-linux.h"
>
>
>
> AREA/CLASS/EXAMPLE AFFECTED: class ACE_Thread_Timer_Queue_Adapter
> (file: Timer_Queue_Adapter.[h,inl,cpp])
>
>
>
> DOES THE PROBLEM AFFECT: Execution
>
>
>
> SYNOPSIS:
>
> The thread created by the class ACE_Thread_Timer_Queue_Adapter will
> not pend and just continue to consume the CPU.
>
> The problem occurs when the TQ Type is not using the
> ACE_Default_Time_Policy.
>
>
>
> DESCRIPTION:
>
>
>
> Declaration of the ACE_Thread_Timer_Queue_Adapter:
>
>
>
> template <class TQ, class TYPE = ACE_Event_Handler*>
>
> class ACE_Thread_Timer_Queue_Adapter : public ACE_Task_Base
>
>
>
> The issue is when class TQ's Time Policy is not the
> ACE_Default_Time_Policy. The root of the problem is class's
>
> condition_ is always expecting a time value based on the default time
> policy (Wall Clock Time). In the
>
> ACE_Thread_Timer_Queue_Adapter::svc method the absolute time to wait
> for a scheduled timer will be based on TQ's
>
> Time Policy (line 279), but condition_ is expecting an absolute time
> to be based on the default time policy (Wall Clock Time)
>
> (line 282).
>
>
>
>
>
> From the ACE_Thread_Timer_Queue_Adapter::svc method, lines 268-283
>
>
>
> // Compute the remaining time, being careful not to sleep
>
> // for "negative" amounts of time.
>
> ACE_Time_Value const tv_curr =
>
> this->timer_queue_->gettimeofday ();
>
> ACE_Time_Value const tv_earl =
>
> this->timer_queue_->earliest_time ();
>
>
>
> if (tv_earl > tv_curr)
>
> {
>
> // The earliest time on the Timer_Queue lies in future;
>
> // convert the tv to an absolute time.
>
> ACE_Time_Value const tv =
> this->timer_queue_->gettimeofday () + (tv_earl - tv_curr); // tv
> based on the Time from the TQ's Time Policy
>
> // ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("waiting until
> %u.%3.3u secs\n"),
>
> // tv.sec(), tv.msec()));
>
> this->condition_.wait (&tv); // condition_ is
> expecting an absolute time to always be based on the default time
> policy (Wall Clock Time)
>
> }
>
>
>
> REPEAT BY:
>
>
>
> 1) Declare the ACE_Thread_Timer_Queue_Adapter with the following
> parameters:
>
>
>
> class MyTimerInterface : public ACE_Task<ACE_MT_SYNCH,
> ACE_Monotonic_Time_Policy>
>
>
>
> ......
>
> /**
>
> * \brief Timer Interface Timer Heap Type
>
> */
>
> typedef ACE_Timer_Heap_T<ACE_Event_Handler *,
>
> ACE_Event_Handler_Handle_Timeout_Upcall,
>
> ACE_SYNCH_RECURSIVE_MUTEX,
>
> ACE_Monotonic_Time_Policy> MyTimerHeapTyp;
>
> /**
>
> * \brief My Interface Timer Queue Thread Type
>
> */
>
> typedef ACE_Thread_Timer_Queue_Adapter<MyTimerHeapTyp>
> MyTimerQThreadTyp;
>
>
>
> MyTimerQThreadTyp myTimerT;
>
>
>
> .....
>
>
>
> };
>
>
>
> 2) Schedule a periodic timer with myTimerT
>
> 3) Monitor the CPU utilization of the process or process threads with
> top.
>
> 4) top should show the thread created by myTimerT member constantly
> running and consuming the CPU.
>
> 5) I use the following API call to set the thread's name to know
> which of my threads are displayed in top.
>
> /*
>
> ** Set the Linux Process/Thread Name
>
> */
>
> prctl(PR_SET_NAME, "MyTimerT");
>
>
>
> Just add the line to the MyTimerInterface::handle_timeout method
> of the ACE_Event_Hander object passed to the schedule method.
>
>
>
> this->myTimerT.schedule(this, .....)
>
>
>
> When you use the "top -H -p <Process's PID>", you should see
> "MyTimerT" under top's "COMMAND" column.
>
>
>
> SAMPLE FIX/WORKAROUND:
>
>
>
> I think the based solution would be to add a ACE Condition
> Attributes data member similar to class Message_Queue_T
>
>
>
> I got this declaration from Message_Queue_T.h, lines 611-615. Add
> the following lines to the private section of
>
> ACE_Thread_Timer_Queue_Adapter class:
>
> /// Attributes to initialize conditions with.
>
> /* We only need this because some crappy compilers can't
>
> properly handle initializing the conditions with
>
> temporary objects. */
>
> ACE_Condition_Attributes_T<TIME_POLICY> cond_attr_;
>
>
>
> Update line 162 in Timer_Queue_Adapter.cpp:
>
> condition_ (mutex_),
>
> Change To:
>
> condition_ (mutex_, cond_attr_),
>
>
>
> The issue with the fix is the TIME_POLICY Type. The current
> declaration has TIME_POLICY in the
>
> TQ Type, so it is not currently available in the
> ACE_Thread_Timer_Queue_Adapter. My knowledge on
>
> C++ Templates is not great. So not positive if there is a way for
> the ACE_Thread_Timer_Queue_Adapter
>
> class to have access to the TIME_POLICY from the TQ type to declare
> a data member. If it is not possible,
>
> then TIME_POLICY type would need to be added to the
> ACE_Thread_Timer_Queue_Adapter declaration.
>
>
>
> Currently:
>
> template <class TQ, class TYPE = ACE_Event_Handler*>
>
> class ACE_Thread_Timer_Queue_Adapter : public ACE_Task_Base
>
>
>
> My Change:
>
> template <class TQ, class TYPE = ACE_Event_Handler*, typename
> TIME_POLICY = ACE_Default_Time_Policy>
>
> class ACE_Thread_Timer_Queue_Adapter : public ACE_Task_Base
>
>
>
> Adding the TIME_POLICY at the end and defaulting the value to
> ACE_Default_Time_Policy should not cause compilation errors
>
> with existing code.
>
>
>
> My one concern is the TQ's TIME_POLICY could be out of synch with
> ACE_Thread_Timer_Queue_Adapter's TIME_POLICY. Hopefully
>
> there is a way to do a validation check at compile time. As of now,
> I do not know how to do a validation check if the two
>
> TIME_POLICY types were not the same.
>
>
>
> Each of the method's declaration had to be updated in the
> Timer_Queue_Adapter.inl and Timer_Queue_Adapter.cpp.
>
>
>
> I have implemented, compiled, and tested to
> ACE_Thread_Timer_Queue_Adapter class. The problem with the CPU
> processing has
>
> gone away when using the ACE_Monotonic_Time_Policy.
>
>
>
> The new code is the following:
>
>
>
> class MyTimerInterface : public ACE_Task<ACE_MT_SYNCH,
> ACE_Monotonic_Time_Policy>
>
>
>
> ......
>
> /**
>
> * \brief Timer Interface Timer Heap Type
>
> */
>
> typedef ACE_Timer_Heap_T<ACE_Event_Handler *,
>
> ACE_Event_Handler_Handle_Timeout_Upcall,
>
> ACE_SYNCH_RECURSIVE_MUTEX,
>
> ACE_Monotonic_Time_Policy> MyTimerHeapTyp;
>
> /**
>
> * \brief My Interface Timer Queue Thread Type
>
> */
>
> typedef ACE_Thread_Timer_Queue_Adapter<MyTimerHeapTyp,
>
> ACE_Event_Handler *,
>
> ACE_Monotonic_Time_Policy>
> MyTimerQThreadTyp;
>
>
>
> MyTimerQThreadTyp myTimerT;
>
>
>
> .....
>
>
>
> };
>
>
>
> Chuck Wanner
>
>
>
>
> _______________________________________________
> ace-users mailing list
> ace-users at list.isis.vanderbilt.edu
> http://list.isis.vanderbilt.edu/cgi-bin/mailman/listinfo/ace-users
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://list.isis.vanderbilt.edu/pipermail/ace-users/attachments/20190219/b8d6bb6d/attachment-0001.html>
More information about the ace-users
mailing list