[scheduler] Fix missing lock when recycling items in defer queue processing (#12343)

This commit is contained in:
J. Nick Koston
2025-12-07 13:30:22 -06:00
committed by Jonathan Swoboda
parent b6336f9e63
commit b213555dd2
2 changed files with 9 additions and 1 deletions

View File

@@ -744,6 +744,10 @@ bool HOT Scheduler::SchedulerItem::cmp(const std::unique_ptr<SchedulerItem> &a,
: (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) {
if (!item)
return;

View File

@@ -275,6 +275,7 @@ class Scheduler {
// Helper to recycle a SchedulerItem back to the pool.
// 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.
// IMPORTANT: Caller must hold the scheduler lock before calling this function.
void recycle_item_main_loop_(std::unique_ptr<SchedulerItem> item);
// Helper to perform full cleanup when too many items are cancelled
@@ -331,7 +332,10 @@ class Scheduler {
now = this->execute_item_(item.get(), now);
}
// 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