From b266fb37a3ba60c98cbb140b16620a6b33844e8b Mon Sep 17 00:00:00 2001 From: Guillermo Ruffino Date: Thu, 15 Oct 2020 10:12:31 -0300 Subject: [PATCH] Fix scheduler with too many cancelled timers (#1309) * Fix scheduler with too many cancelled timers * lint * use variable name --- esphome/core/scheduler.cpp | 26 +++++++++++++++++++++++++- esphome/core/scheduler.h | 1 + 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index e61b2b13c6..9be39f4938 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -8,6 +8,7 @@ namespace esphome { static const char *TAG = "scheduler"; static const uint32_t SCHEDULER_DONT_RUN = 4294967295UL; +static const uint32_t MAX_LOGICALLY_DELETED_ITEMS = 10; // Uncomment to debug scheduler // #define ESPHOME_DEBUG_SCHEDULER @@ -107,6 +108,26 @@ void ICACHE_RAM_ATTR HOT Scheduler::call() { } #endif // ESPHOME_DEBUG_SCHEDULER + auto to_remove_was = to_remove_; + auto items_was = items_.size(); + // If we have too many items to remove + if (to_remove_ > MAX_LOGICALLY_DELETED_ITEMS) { + std::vector> valid_items; + while (!this->empty_()) { + auto item = std::move(this->items_[0]); + this->pop_raw_(); + valid_items.push_back(std::move(item)); + } + this->items_ = std::move(valid_items); + + // The following should not happen unless I'm missing something + if (to_remove_ != 0) { + ESP_LOGW(TAG, "to_remove_ was %u now: %u items where %zu now %zu. Please report this", to_remove_was, to_remove_, + items_was, items_.size()); + to_remove_ = 0; + } + } + while (!this->empty_()) { // use scoping to indicate visibility of `item` variable { @@ -147,6 +168,7 @@ void ICACHE_RAM_ATTR HOT Scheduler::call() { if (item->remove) { // We were removed/cancelled in the function call, stop + to_remove_--; continue; } @@ -182,6 +204,7 @@ void HOT Scheduler::cleanup_() { if (!item->remove) return; + to_remove_--; this->pop_raw_(); } } @@ -193,7 +216,8 @@ void HOT Scheduler::push_(std::unique_ptr item) { this bool HOT Scheduler::cancel_item_(Component *component, const std::string &name, Scheduler::SchedulerItem::Type type) { bool ret = false; for (auto &it : this->items_) - if (it->component == component && it->name == name && it->type == type) { + if (it->component == component && it->name == name && it->type == type && !it->remove) { + to_remove_++; it->remove = true; ret = true; } diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index 5688058a1e..d1839cb4a7 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -61,6 +61,7 @@ class Scheduler { std::vector> to_add_; uint32_t last_millis_{0}; uint8_t millis_major_{0}; + uint32_t to_remove_{0}; }; } // namespace esphome