mirror of
https://github.com/ceph/ceph
synced 2025-02-22 10:37:15 +00:00
TaskFinisher: cancel all tasks wait until finisher done
Otherwise, caller may think pending task won't be executed but actually finisher may execute callback which may cause refer to freed object. Signed-off-by: Haomai Wang <haomai@xsky.com>
This commit is contained in:
parent
e7aff3da8b
commit
40c5679ef0
@ -31,6 +31,7 @@ namespace librbd {
|
||||
|
||||
using namespace image_watcher;
|
||||
using namespace watch_notify;
|
||||
using util::create_async_context_callback;
|
||||
using util::create_context_callback;
|
||||
using util::create_rados_safe_callback;
|
||||
|
||||
@ -120,7 +121,10 @@ void ImageWatcher::unregister_watch(Context *on_finish) {
|
||||
ldout(m_image_ctx.cct, 10) << this << " unregistering image watcher" << dendl;
|
||||
|
||||
cancel_async_requests();
|
||||
m_task_finisher->cancel_all();
|
||||
|
||||
C_Gather *g = new C_Gather(m_image_ctx.cct, create_async_context_callback(
|
||||
m_image_ctx, on_finish));
|
||||
m_task_finisher->cancel_all(g->new_sub());
|
||||
|
||||
{
|
||||
RWLock::WLocker l(m_watch_lock);
|
||||
@ -128,17 +132,17 @@ void ImageWatcher::unregister_watch(Context *on_finish) {
|
||||
m_watch_state = WATCH_STATE_UNREGISTERED;
|
||||
|
||||
librados::AioCompletion *aio_comp = create_rados_safe_callback(
|
||||
new C_UnwatchAndFlush(m_image_ctx.md_ctx, on_finish));
|
||||
new C_UnwatchAndFlush(m_image_ctx.md_ctx, g->new_sub()));
|
||||
int r = m_image_ctx.md_ctx.aio_unwatch(m_watch_handle, aio_comp);
|
||||
assert(r == 0);
|
||||
aio_comp->release();
|
||||
g->activate();
|
||||
return;
|
||||
} else if (m_watch_state == WATCH_STATE_ERROR) {
|
||||
m_watch_state = WATCH_STATE_UNREGISTERED;
|
||||
}
|
||||
}
|
||||
|
||||
on_finish->complete(0);
|
||||
g->activate();
|
||||
}
|
||||
|
||||
void ImageWatcher::flush(Context *on_finish) {
|
||||
|
@ -63,13 +63,17 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void cancel_all() {
|
||||
Mutex::Locker l(*m_lock);
|
||||
for (typename TaskContexts::iterator it = m_task_contexts.begin();
|
||||
it != m_task_contexts.end(); ++it) {
|
||||
delete it->second.first;
|
||||
void cancel_all(Context *comp) {
|
||||
{
|
||||
Mutex::Locker l(*m_lock);
|
||||
for (typename TaskContexts::iterator it = m_task_contexts.begin();
|
||||
it != m_task_contexts.end(); ++it) {
|
||||
delete it->second.first;
|
||||
m_safe_timer->cancel_event(it->second.second);
|
||||
}
|
||||
m_task_contexts.clear();
|
||||
}
|
||||
m_task_contexts.clear();
|
||||
m_finisher->queue(comp);
|
||||
}
|
||||
|
||||
bool add_event_after(const Task& task, double seconds, Context *ctx) {
|
||||
|
Loading…
Reference in New Issue
Block a user