Skip to content

Cannot cancel during canceling

We have seen libvda throw an error sometimes saying "Cannot cancel during canceling". This seems to happen if it gets a new cancel instant action while it is already in the transition state of canceling. To handle this more gracefully, I have added some checks to see if it is already in a transition state as you see here. Please let me know if this seems reasonable to you:

`bool Scheduler::isInTransitionState() { return this->state_->getState() == SchedulerStateType::k_pausing || this->state_->getState() == SchedulerStateType::k_resuming || this->state_->getState() == SchedulerStateType::k_canceling; }

void Scheduler::cancel(std::optional lock) { auto e_lock = this->ensureLock(std::move(lock));

if (this->state_ == nullptr) { throw vda5050pp::VDA5050PPNullPointer(MK_EX_CONTEXT("state_ is nullptr")); }

if (Scheduler::isInTransitionState()) { getOrderLogger()->debug("Scheduler::cancel() - Already in transition state, ignoring second cancel call."); return; }

getOrderLogger()->debug("Scheduler::cancel() pre_state_={}", this->state_->describe()); auto [state, update] = this->state_->cancel(); this->state_ = std::move(state); getOrderLogger()->debug("Scheduler::cancel() post_state_={}", this->state_->describe());

if (update) { this->update(std::move(e_lock)); } }

void Scheduler::pause(std::optional lock) { auto e_lock = this->ensureLock(std::move(lock));

if (this->state_ == nullptr) { throw vda5050pp::VDA5050PPNullPointer(MK_EX_CONTEXT("state_ is nullptr")); }

if (Scheduler::isInTransitionState()) { getOrderLogger()->debug("Scheduler::cancel() - Already in transition state, ignoring second pause call."); return; }

getOrderLogger()->debug("Scheduler::pause() pre_state_={}", this->state_->describe()); auto [state, update] = this->state_->pause(); this->state_ = std::move(state); getOrderLogger()->debug("Scheduler::pause() post_state_={}", this->state_->describe());

if (update) { this->update(std::move(e_lock)); } }

void Scheduler::resume(std::optional lock) { auto e_lock = this->ensureLock(std::move(lock));

if (this->state_ == nullptr) { throw vda5050pp::VDA5050PPNullPointer(MK_EX_CONTEXT("state_ is nullptr")); }

if (Scheduler::isInTransitionState()) { getOrderLogger()->debug("Scheduler::cancel() - Already in transition state, ignoring second resume call."); return; }

getOrderLogger()->debug("Scheduler::resume() pre_state_={}", this->state_->describe()); auto [state, update] = this->state_->resume(); this->state_ = std::move(state); getOrderLogger()->debug("Scheduler::resume() post_state_={}", this->state_->describe());

if (update) { this->update(std::move(e_lock)); } }`

Edited by Bastian Petersson