AbstractWriteLog::shut_down() calls perf_stop(), which deletes
m_perfcounter, but the 5s periodic_stats timer is only canceled later
in the destructor. If it fires in between, periodic_stats ->
update_image_cache_state dereferences the freed m_perfcounter. Cancel
the timer under m_timer_lock first.
Destroying an AbstractWriteLog that was init()'ed without a matching
shut_down() is illegal, so the cancel_event() in the destructor is now
redundant and is dropped.
Fixes: https://tracker.ceph.com/issues/77501
Signed-off-by: Sun Yuechi <sunyuechi@iscas.ac.cn>
AbstractWriteLog<I>::~AbstractWriteLog() {
ldout(m_image_ctx.cct, 15) << "enter" << dendl;
{
- std::lock_guard timer_locker(*m_timer_lock);
std::lock_guard locker(m_lock);
- m_timer->cancel_event(m_timer_ctx);
m_thread_pool.stop();
ceph_assert(m_deferred_ios.size() == 0);
ceph_assert(m_ops_to_flush.size() == 0);
Context *ctx = new LambdaContext(
[this, on_finish](int r) {
+ {
+ std::lock_guard timer_locker(*m_timer_lock);
+ m_timer->cancel_event(m_timer_ctx);
+ m_timer_ctx = nullptr;
+ }
if (m_perfcounter) {
perf_stop();
}