diff options
author | Alan Conway <aconway@apache.org> | 2016-06-22 20:41:55 +0000 |
---|---|---|
committer | Alan Conway <aconway@apache.org> | 2016-06-22 20:41:55 +0000 |
commit | 7b8a91375dc0528e2c15686ab71c3647ac3e2f96 (patch) | |
tree | 37b11722254d3109e23ebe676a1137840120a107 /qpid/cpp/src/qpid/management/ManagementObject.cpp | |
parent | e1d9be1b3590c79a0b2a6b6ad4cd3e6a65877401 (diff) | |
download | qpid-python-7b8a91375dc0528e2c15686ab71c3647ac3e2f96.tar.gz |
QPID-7306: Fix race conditions during Queue destruction.
Stack traces indicate a Queue was being destroyed concurrently while still in
use by its ManagedObject.
ManagedObject holds a plain pointer to the Manageable object (e.g. Queue) it
belongs to. The Manageable calls ManagedObject::resourceDestroy() when it is
deleted, but without any locking.
Added a locked wrapper class ManageablePtr so destroy is atomic with respect to
other calls via ManageablePtr, calls after pointer is reset to 0 in destroy()
are skipped.
Call resourceDestroy() in Queue::~Queue if it was not called already. This is
probably redundant given given the fixes above but can't hurt.
Queue::destroyed() was also being called without locking and could be called
concurrrently, e.g. if auto-delete happens concurrently with delete via QMF or
by a 0-10 client. Moved the destroyed() call into QueueRegistry::destroy(),
using QueueRegistry lock to guarantee it is called exactly once.
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1749782 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/cpp/src/qpid/management/ManagementObject.cpp')
-rw-r--r-- | qpid/cpp/src/qpid/management/ManagementObject.cpp | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/qpid/cpp/src/qpid/management/ManagementObject.cpp b/qpid/cpp/src/qpid/management/ManagementObject.cpp index 019963e832..f18f575ff8 100644 --- a/qpid/cpp/src/qpid/management/ManagementObject.cpp +++ b/qpid/cpp/src/qpid/management/ManagementObject.cpp @@ -23,6 +23,7 @@ #include "qpid/management/ManagementObject.h" #include "qpid/framing/FieldTable.h" #include "qpid/framing/Buffer.h" +#include "qpid/framing/reply_exceptions.h" #include "qpid/sys/Time.h" #include "qpid/sys/Thread.h" #include "qpid/log/Statement.h" @@ -245,11 +246,37 @@ ostream& operator<<(ostream& out, const ObjectId& i) }} +// Called with lock held +Manageable* ManagementObject::ManageablePtr::get() const { + if (ptr == 0) + throw framing::ResourceDeletedException("managed object deleted"); + return ptr; +} + +void ManagementObject::ManageablePtr::reset() { + Mutex::ScopedLock l(lock); + ptr = 0; +} + +uint32_t ManagementObject::ManageablePtr::ManagementMethod( + uint32_t methodId, Args& args, std::string& text) +{ + Mutex::ScopedLock l(lock); + return get()->ManagementMethod(methodId, args, text); +} + +bool ManagementObject::ManageablePtr:: AuthorizeMethod( + uint32_t methodId, Args& args, const std::string& userId) +{ + Mutex::ScopedLock l(lock); + return get()->AuthorizeMethod(methodId, args, userId); +} + ManagementObject::ManagementObject(Manageable* _core) : createTime(qpid::sys::Duration::FromEpoch()), destroyTime(0), updateTime(createTime), configChanged(true), instChanged(true), deleted(false), - coreObject(_core), flags(0), forcePublish(false) {} + manageable(_core), flags(0), forcePublish(false) {} void ManagementObject::setUpdateTime() { @@ -261,6 +288,7 @@ void ManagementObject::resourceDestroy() QPID_LOG(trace, "Management object marked deleted: " << getObjectId().getV2Key()); destroyTime = sys::Duration::FromEpoch(); deleted = true; + manageable.reset(); } int ManagementObject::maxThreads = 1; |