----------------------------------------------------------- This is an automatically generated e-mail. To reply, visit: https://reviews.apache.org/r/14555/ -----------------------------------------------------------
Review request for qpid, Gordon Sim and Kim van der Riet. Bugs: https://issues.apache.org/jira/browse/QPID-5214 https://issues.apache.org/jira/browse/https://issues.apache.org/jira/browse/QPID-5214 Repository: qpid Description ------- mrg::msgstore::MessageStoreImpl::enqueue method calls: .. if (queue) { boost::intrusive_ptr<DataTokenImpl> dtokp(new DataTokenImpl); dtokp->addRef(); .. (where in further code calls executed, an exception is raised within the scope of dtokp life) Apparently, boost library has a limitation with throwing exceptions where it forgets to remove some reference to the object, causing delete is not executed when intrusive_ptr variable is gone. See my reproducer below, independend on qpid/store code. Therefore, to workaround it, let release the dtokp manually just before throwing the exception. But I don't fully like adding new parameter to handleIoResult method (and not sure with re-casting dtokp from data_tok* to DataTokenImpl* is done in proper way). Reproducer of boost::intrusive_ptr limitation when throwing exception: let run below program via valgrind, first as is (direct memory loss), and then with "dtokp->release();" line uncommented (no direct memory loss). #include <iostream> #include <boost/intrusive_ptr.hpp> #include <boost/utility.hpp> #include <boost/detail/atomic_count.hpp> class RefCounted : public boost::noncopyable { mutable boost::detail::atomic_count count; public: RefCounted() : count(0) {} void addRef() const { ++count; } void release() const { if (--count==0) released(); } long refCount() { return count; } protected: virtual ~RefCounted() {}; // Allow subclasses to over-ride behavior when refcount reaches 0. virtual void released() const { delete this; } }; // intrusive_ptr support. inline void intrusive_ptr_add_ref(const RefCounted* p) { p->addRef(); } inline void intrusive_ptr_release(const RefCounted* p) { p->release(); } class DataTokenImpl : public RefCounted { public: DataTokenImpl() {} ~DataTokenImpl() {} }; void enqueue_data_record(const DataTokenImpl* dtokp) { // dtokp->release(); throw 20; } int local() { try { boost::intrusive_ptr<DataTokenImpl> dtokp(new DataTokenImpl); dtokp->addRef(); enqueue_data_record(dtokp.get()); } catch (int e) { std::cout << "local: caught exception " << e << std::endl; throw; } return 0; } int main(void) { try { local(); } catch (int e) { std::cout << "main: caught exception " << e << std::endl; } return 0; } Diffs ----- /trunk/qpid/cpp/src/qpid/legacystore/JournalImpl.h 1528730 /trunk/qpid/cpp/src/qpid/legacystore/JournalImpl.cpp 1528730 Diff: https://reviews.apache.org/r/14555/diff/ Testing ------- Valgrind used for reproducer returned no memory related problems, automated tests passed. Thanks, Pavel Moravec