Bug and patch for boost.python with enable_shared_from_this
Hi all, A month ago or so we discovered a bug in Boost.Python that manifests when using enable_shared_from_this. Here is a test case that demonstrates the bug: #include <boost/python.hpp> #include <boost/enable_shared_from_this.hpp> using namespace boost; using namespace boost::python; class Test; typedef shared_ptr<Test> TestPtr; class Test : public enable_shared_from_this<Test> { public: static TestPtr construct() { return TestPtr(new Test); } void act() { TestPtr kungFuDeathGrip(shared_from_this()); } void take(TestPtr t) { } }; void Export_test() { class_<Test, TestPtr, noncopyable>("Test") .def("construct", &Test::construct) .staticmethod("construct") .def("act", &Test::act) .def("take", &Test::take) ; } And here is the Python: x = Test.construct() x.take(x) x.act() The bug (as I understand it) is that the shared_ptr_from_python converter creates a new shared_ptr for the Test instance to pass it into C++. This new shared_ptr has a nop deleter, except that it keeps the Python object alive as long as the new shared_ptr is alive. The problem here is that creating a shared_ptr to an object of type T when T is enable_shared_from_this<T> resets the weak pointer inside of enable_shared_from_this<T>. (See shared_ptr's constructors for the details of the implementation.) A fix that passes the test above and has worked for us is to change shared_ptr's constructor to accept a dont_enable_shared_from_this argument and pass that in from the shared_ptr_from_python converter. The patch is attached (against boost 1.33, but the bug didn't look fixed in 1.34 either). Cheers, Chad p.s. I have seen other people with this problem as well. Googling for bad_weak_ptr turns up several results.
It worked! That problem had been driving me crazy for the past 2 days. I don't know why I couldn't find the answer via Google. Perhaps its because of all the brain damage from my Java programming. Thank you so much. - John 2008/2/10 Chad Austin <chad@imvu.com>:
Hi all,
A month ago or so we discovered a bug in Boost.Python that manifests when using enable_shared_from_this. Here is a test case that demonstrates the bug:
#include <boost/python.hpp> #include <boost/enable_shared_from_this.hpp>
using namespace boost; using namespace boost::python;
class Test; typedef shared_ptr<Test> TestPtr;
class Test : public enable_shared_from_this<Test> { public: static TestPtr construct() { return TestPtr(new Test); }
void act() { TestPtr kungFuDeathGrip(shared_from_this()); }
void take(TestPtr t) { } };
void Export_test() { class_<Test, TestPtr, noncopyable>("Test") .def("construct", &Test::construct) .staticmethod("construct")
.def("act", &Test::act) .def("take", &Test::take) ; }
And here is the Python:
x = Test.construct() x.take(x) x.act()
The bug (as I understand it) is that the shared_ptr_from_python converter creates a new shared_ptr for the Test instance to pass it into C++. This new shared_ptr has a nop deleter, except that it keeps the Python object alive as long as the new shared_ptr is alive. The problem here is that creating a shared_ptr to an object of type T when T is enable_shared_from_this<T> resets the weak pointer inside of enable_shared_from_this<T>. (See shared_ptr's constructors for the details of the implementation.) A fix that passes the test above and has worked for us is to change shared_ptr's constructor to accept a dont_enable_shared_from_this argument and pass that in from the shared_ptr_from_python converter. The patch is attached (against boost 1.33, but the bug didn't look fixed in 1.34 either).
Cheers, Chad
p.s. I have seen other people with this problem as well. Googling for bad_weak_ptr turns up several results.
_______________________________________________ C++-sig mailing list C++-sig@python.org http://mail.python.org/mailman/listinfo/c++-sig
It's quite early to claim problem (completely) solved. Niether of described mechanismes would help you if class Test is wrapped and derived from and require PyObject alive along with. As well as Peter's shared_ptr patches to date. Because boost::python::object::ob_refcnt does not increases/decreases on creation/deletion of an shared_ptr constructed from shared_from_this(). Any ideas?.. -- View this message in context: http://www.nabble.com/Bug-and-patch-for-boost.python-with-enable_shared_from... Sent from the Python - c++-sig mailing list archive at Nabble.com.
participants (3)
-
Chad Austin -
John Trimble -
Tim J. Ranger