Ignore:
Timestamp:
Feb 27, 2024, 10:18:17 PM (20 months ago)
Author:
Frederik Heber <frederik.heber@…>
Branches:
Candidate_v1.7.0, stable
Children:
399c69
Parents:
d203d1e
git-author:
Frederik Heber <frederik.heber@…> (02/25/24 23:14:04)
git-committer:
Frederik Heber <frederik.heber@…> (02/27/24 22:18:17)
Message:

FIX: ActionQueue no locked on CurrentAction access.

  • actionqueue[CurrentAction] without mutex locking.
  • getCurrentAction() without mutex locking.
  • extracted stepOnToNextAction().
  • using recursive_mutex instead of normal to allow nested locks.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Actions/ActionQueue.cpp

    rd203d1e r0427d1  
    4343
    4444#include <boost/date_time/posix_time/posix_time.hpp>
     45#include <boost/thread/recursive_mutex.hpp>
    4546#include <boost/version.hpp>
    4647#include <iterator>
     
    147148  Action *newaction = _action->clone(state);
    148149  newaction->prepare(state);
    149   mtx_queue.lock();
    150   tempqueue.push_back( newaction );
    151   const bool tempqueue_notempty = !tempqueue.empty();
    152   mtx_queue.unlock();
     150  bool tempqueue_notempty;
     151  {
     152    boost::recursive_mutex::scoped_lock lock(mtx_queue);
     153    tempqueue.push_back( newaction );
     154    tempqueue_notempty = !tempqueue.empty();
     155  }
    153156  setRunThreadIdle( !((!isIdle()) || tempqueue_notempty) );
    154157#endif
     
    158161{
    159162#ifdef HAVE_ACTION_THREAD
    160   boost::unique_lock<boost::mutex> lock(mtx_queue);
     163  boost::recursive_mutex::scoped_lock lock(mtx_queue);
    161164#endif
    162165  bool status = (CurrentAction == actionqueue.size());
     
    188191const Action& ActionQueue::getCurrentAction() const
    189192{
     193#ifdef HAVE_ACTION_THREAD
     194  boost::recursive_mutex::scoped_lock lock(mtx_queue);
     195#endif
    190196  return *const_cast<const Action *>(actionqueue[CurrentAction]);
    191197}
     
    209215//    LOG(1, "DEBUG: Start of ActionQueue's run() loop.");
    210216    // call all currently present Actions
    211     mtx_queue.lock();
    212217    insertTempQueue();
    213     mtx_queue.unlock();
    214218    bool status = !isIdle();
    215219    while (status) {
    216220      //      boost::this_thread::disable_interruption di;
    217       LOG(0, "Calling Action " << actionqueue[CurrentAction]->getName() << " ... ");
    218221      try {
    219         if (!isDryRun(actionqueue[CurrentAction]))
    220           actionqueue[CurrentAction]->call();
    221         pushStatus("SUCCESS: Action "+actionqueue[CurrentAction]->getName()+" successful.");
     222        // pick next action to run
     223        Action * action_to_run;
     224        {
     225          boost::recursive_mutex::scoped_lock lock(mtx_queue);
     226          action_to_run = actionqueue[CurrentAction];
     227        }
     228        LOG(0, "Calling Action " << action_to_run->getName() << " ... ");
     229        // run action
     230        if (!isDryRun(action_to_run))
     231          action_to_run->call();
     232        pushStatus("SUCCESS: Action "+action_to_run->getName()+" successful.");
    222233        lastActionOk = true;
    223234      } catch(ActionFailureException &e) {
     
    239250        OBSERVE;
    240251        NOTIFY(ActionQueued);
    241         _lastchangedaction = actionqueue[CurrentAction];
    242         mtx_queue.lock();
    243         CurrentAction++;
    244         mtx_queue.unlock();
     252        stepOnToNextAction();
    245253      }
    246       // access actionqueue, hence using mutex
    247       mtx_queue.lock();
    248254      // insert new actions (before [CurrentAction]) if they have been spawned
    249255      // we must have an extra vector for this, as we cannot change actionqueue
    250256      // while an action instance is "in-use"
    251257      insertTempQueue();
    252       mtx_queue.unlock();
    253258      status = !isIdle();
    254259    }
    255     mtx_queue.lock();
    256     const bool tempqueue_notempty = !tempqueue.empty();
    257     mtx_queue.unlock();
     260    bool tempqueue_notempty;
     261    {
     262      boost::recursive_mutex::scoped_lock lock(mtx_queue);
     263      tempqueue_notempty = !tempqueue.empty();
     264    }
    258265    setRunThreadIdle( !((!isIdle()) || tempqueue_notempty) );
    259266    cond_idle.notify_one();
     
    262269}
    263270
     271void ActionQueue::stepOnToNextAction()
     272{
     273   boost::recursive_mutex::scoped_lock lock(mtx_queue);
     274   _lastchangedaction = actionqueue[CurrentAction];
     275   CurrentAction++;
     276}
     277
    264278void ActionQueue::insertTempQueue()
    265279{
    266280  if (!tempqueue.empty()) {
    267     ActionQueue_t::iterator InsertionIter = actionqueue.begin();
    268     std::advance(InsertionIter, CurrentAction);
    269     actionqueue.insert( InsertionIter, tempqueue.begin(), tempqueue.end() );
     281    // access actionqueue, hence using mutex
     282    boost::recursive_mutex::scoped_lock lock(mtx_queue);
     283    actionqueue.insert( actionqueue.end(), tempqueue.begin(), tempqueue.end() );
    270284    tempqueue.clear();
    271285  }
     
    359373{
    360374#ifdef HAVE_ACTION_THREAD
    361   mtx_queue.lock();
     375  boost::recursive_mutex::scoped_lock lock(mtx_queue);
    362376#endif
    363377  LOG(1, "Removing all Actions from position " << _fromAction << " onward.");
     
    371385#ifdef HAVE_ACTION_THREAD
    372386  CurrentAction = actionqueue.size();
    373   mtx_queue.unlock();
    374387#endif
    375388}
Note: See TracChangeset for help on using the changeset viewer.