[C++-sig] boost::python and threads
Paul Scruby
paul at gingernut.tv
Fri Jul 3 13:15:10 CEST 2009
I am having some problems using boost::python with boost::thread. I'm using
threads because I want to run some tasks in the background when I'm using
the Python's interactive shell. However, when I use get_override() to call
a Python method from another boost::thread it crashes internally. For
example:
#include <boost/python.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>
using namespace boost::python;
class Ticker
: public wrapper<Ticker>
{
private:
bool run_;
volatile bool * running_;
boost::thread * thread_;
boost::xtime xt_;
public:
Ticker() : running_(&run_) { *running_ = false; }
void operator()()
{
while (*running_)
{
boost::xtime_get(&xt_, boost::TIME_UTC);
++xt_.sec;
boost::thread::sleep(xt_);
onTick();
}
}
void run()
{
if (*running_ == false)
{
*running_ = true;
thread_ = new boost::thread(*this);
}
}
void stop()
{
if (*running_ == true)
{
*running_ = false;
thread_->join();
delete thread_;
}
}
virtual void onTick() { get_override("onTick")(); }
void default_onTick() {}
};
BOOST_PYTHON_MODULE(tick)
{
class_<Ticker, boost::noncopyable> ("Ticker")
.def("run", &Ticker::run)
.def("stop", &Ticker::stop)
.def("onTick", &Ticker::default_onTick);
}
Here is a test script that which will crash when you import it into Python's
interactive shell.
from tick import Ticker
class MyTicker(Ticker):
def onTick(self):
print "Each second"
myticker = MyTicker()
myticker.run()
I ran this test initially on Python 2.4.4 with the Sun C++ 5.9 compiler on
Solaris and I also tested it using Python 2.6.2 with Visual Studio 2008 on
Windows XP.
The call-stack in dbx on Solaris:
>>> t at 2 (l at 2) signal SEGV (no mapping at the fault address) in
PyErr_Restore at 0xfef38fa1
0xfef38fa1: PyErr_Restore+0x0031: movl 0x00000028(%edi),%ecx
Current function is boost::python::override::operator()
99 detail::method_result x(
(dbx) where
current thread: t at 2
[1] PyErr_Restore(0x80652fc, 0x80f1220, 0x0, 0xfe77ee90, 0xfef3951e,
0x80652fc), at 0xfef38fa1
[2] PyErr_SetObject(0x80652fc, 0x80f1220), at 0xfef3901e
[3] PyErr_Format(0x80652fc, 0xfef5c2d8, 0xfef7902c), at 0xfef3951e
[4] PyObject_Call(0xfef88768, 0x806102c, 0x0), at 0xfeee291a
[5] PyEval_CallObjectWithKeywords(0xfef88768, 0x806102c, 0x0), at
0xfef2bf02
[6] PyEval_CallFunction(0xfef88768, 0xfeb02004), at 0xfef434c5
=>[7] boost::python::override::operator()(this = 0xfe77ef30), line 99 in
"override.hpp"
[8] Ticker::onTick(this = 0x810a304), line 48 in "ticker.cc"
[9] Ticker::operator()(this = 0x810a304), line 25 in "ticker.cc"
[10] boost::detail::thread_data<Ticker>::run(this = 0x810a288), line
56 in "thread.hpp"
[11] thread_proxy(0x810a288), at 0xfea78ce4
[12] _thr_setup(0xfe670200), at 0xfee159b9
[13] _lwp_start(0xfe77ef54, 0x80f1220, 0xfe77ee7c, 0xfef3901e,
0x80652fc, 0x80f1220), at 0xfee15ca0
The call-stack in Visual Studio 2008:
python26.dll!1e013595()
[Frames below may be incorrect and/or missing, no symbols loaded for
python26.dll]
python26.dll!1e09ee7d()
> tick.pyd!boost::python::override::operator()() Line 103 + 0x16 bytes
C++
00f3fd64()
tick.pyd!Ticker::operator()() Line 27 + 0xe bytes C++
tick.pyd!boost::detail::thread_data<Ticker>::run() Line 57 C++
tick.pyd!boost::`anonymous namespace'::thread_start_function(void *
param=0x00245f30) Line 168 C++
msvcr90d.dll!_callthreadstartex() Line 348 + 0xf bytes C
msvcr90d.dll!_threadstartex(void * ptd=0x00d46938) Line 331 C
kernel32.dll!7c80b729()
Have a missed a trick using the wrapper, or does boost::python not support
threading?
Many thanks,
Paul
More information about the Cplusplus-sig
mailing list