From: Sage Weil Date: Fri, 24 Oct 2014 16:32:20 +0000 (-0700) Subject: osdc/Objecter: fix tick_event handling in shutdown vs tick race X-Git-Tag: v0.87~8^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=f76f83ce3fa4285e356d643d958a01a69554378d;p=ceph.git osdc/Objecter: fix tick_event handling in shutdown vs tick race If we fail to cancel the tick_event, we rely on tick() itself to clear tick_event. I'm not quite sure how we got this wrong in the previous commit, but this boils down to two cases: 1) shutdown() successfully cancels the event and clears tick_event. tick() never runs. tick_event == NULL when we finish. 2) shutdown() fails to cancel the event because it has already started. In this case tick itself is blocking (or about to block) waiting on the rlock. When it does run it will clear tick_event itself, then see initiazed == 0 and exit without rescheduling. Fixes: #9873 Signed-off-by: Sage Weil --- diff --git a/src/osdc/Objecter.cc b/src/osdc/Objecter.cc index 035127acc99c..c7ea0770a71c 100644 --- a/src/osdc/Objecter.cc +++ b/src/osdc/Objecter.cc @@ -375,8 +375,10 @@ void Objecter::shutdown() if (tick_event) { Mutex::Locker l(timer_lock); - if (timer.cancel_event(tick_event)) + if (timer.cancel_event(tick_event)) { + ldout(cct, 10) << " successfully canceled tick" << dendl; tick_event = NULL; + } } if (m_request_state_hook) { @@ -400,6 +402,7 @@ void Objecter::shutdown() timer.shutdown(); } + assert(tick_event == NULL); } void Objecter::_send_linger(LingerOp *info) @@ -1546,15 +1549,16 @@ void Objecter::tick() ldout(cct, 10) << "tick" << dendl; + // we are only called by C_Tick + assert(tick_event); + tick_event = NULL; + if (!initialized.read()) { // we raced with shutdown + ldout(cct, 10) << __func__ << " raced with shutdown" << dendl; return; } - // we are only called by C_Tick - assert(tick_event); - tick_event = NULL; - set toping; int r = 0;