mirror of
https://github.com/esphome/esphome.git
synced 2026-06-01 01:19:45 +08:00
[scheduler] Fix missing lock when recycling items in defer queue processing (#12343)
This commit is contained in:
committed by
Jonathan Swoboda
parent
b6336f9e63
commit
b213555dd2
@@ -744,6 +744,10 @@ bool HOT Scheduler::SchedulerItem::cmp(const std::unique_ptr<SchedulerItem> &a,
|
|||||||
: (a->next_execution_high_ > b->next_execution_high_);
|
: (a->next_execution_high_ > b->next_execution_high_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Recycle a SchedulerItem back to the pool for reuse.
|
||||||
|
// IMPORTANT: Caller must hold the scheduler lock before calling this function.
|
||||||
|
// This protects scheduler_item_pool_ from concurrent access by other threads
|
||||||
|
// that may be acquiring items from the pool in set_timer_common_().
|
||||||
void Scheduler::recycle_item_main_loop_(std::unique_ptr<SchedulerItem> item) {
|
void Scheduler::recycle_item_main_loop_(std::unique_ptr<SchedulerItem> item) {
|
||||||
if (!item)
|
if (!item)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -275,6 +275,7 @@ class Scheduler {
|
|||||||
// Helper to recycle a SchedulerItem back to the pool.
|
// Helper to recycle a SchedulerItem back to the pool.
|
||||||
// IMPORTANT: Only call from main loop context! Recycling clears the callback,
|
// IMPORTANT: Only call from main loop context! Recycling clears the callback,
|
||||||
// so calling from another thread while the callback is executing causes use-after-free.
|
// so calling from another thread while the callback is executing causes use-after-free.
|
||||||
|
// IMPORTANT: Caller must hold the scheduler lock before calling this function.
|
||||||
void recycle_item_main_loop_(std::unique_ptr<SchedulerItem> item);
|
void recycle_item_main_loop_(std::unique_ptr<SchedulerItem> item);
|
||||||
|
|
||||||
// Helper to perform full cleanup when too many items are cancelled
|
// Helper to perform full cleanup when too many items are cancelled
|
||||||
@@ -331,7 +332,10 @@ class Scheduler {
|
|||||||
now = this->execute_item_(item.get(), now);
|
now = this->execute_item_(item.get(), now);
|
||||||
}
|
}
|
||||||
// Recycle the defer item after execution
|
// Recycle the defer item after execution
|
||||||
this->recycle_item_main_loop_(std::move(item));
|
{
|
||||||
|
LockGuard lock(this->lock_);
|
||||||
|
this->recycle_item_main_loop_(std::move(item));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we've consumed all items up to the snapshot point, clean up the dead space
|
// If we've consumed all items up to the snapshot point, clean up the dead space
|
||||||
|
|||||||
Reference in New Issue
Block a user