Hello again, Sorry, I spoke too soon. The good news is that wrapping my virtual method calls into Python between PyGILState_Ensure() and PyGILState_Release() fixed the crash under Python2.6.2 on Windows, but not when I tested it again under Python 2.4.4 on Solaris. Under Python 2.4.4 on SolarisSolaris it now calls and exits the virtual method in Python sucessfully, but then crashes when C++ trys to release the global interpretor lock.
The call-stack with the Sun C++ 5.9 compiler under Solaris is t...@2 (l...@2) signal SEGV (no mapping at the fault address) in sem_invalid at 0xfec453ed 0xfec453ed: sem_invalid+0x0013: movzwl 0x00000006(%eax),%eax Current function is Ticker::operator() 28 PyGILState_Release(state_); (dbx) where current thread: t...@2 [1] sem_invalid(0x0), at 0xfec453ed [2] _sem_post(0x0), at 0xfec454c4 [3] PyThread_release_lock(0x0, 0xfe77ef2c, 0xfef43eba, 0x80c55c0, 0xfe77ef38, 0xfef441b5), at 0xfef492dc [4] PyEval_ReleaseLock(0x80c55c0, 0xfe77ef38, 0xfef441b5, 0xfeb12aec, 0xfe77ef70, 0xfeafb2e3), at 0xfef27abe [5] PyThreadState_DeleteCurrent(0xfeb12aec, 0xfe77ef70, 0xfeafb2e3, 0x1, 0x0, 0x80a3140), at 0xfef43eba [6] PyGILState_Release(0x1, 0x0), at 0xfef441b5 =>[7] Ticker::operator()(this = 0x810a304), line 28 in "ticker.cc" [8] boost::detail::thread_data<Ticker>::run(this = 0x810a288), line 56 in "thread.hpp" [9] thread_proxy(0x810a288), at 0xfea78ce4 [10] _thr_setup(0xfe670200), at 0xfee159b9 [11] _lwp_start(0xfe77ef08, 0xfec454c4, 0x0, 0xfe77ef54, 0x80c55c0, 0xfe77ef14), at 0xfee15ca0 Do you think it's worth repeating this test using gcc/linux, or do you think that this is just a limitation of using Python with threads? Thanks again, Paul t...@2 (l...@2) signal SEGV (no mapping at the fault address) in sem_invalid at 0xfec453ed 0xfec453ed: sem_invalid+0x0013: movzwl 0x00000006(%eax),%eax Current function is Ticker::operator() 28 PyGILState_Release(state_); (dbx) where current thread: t...@2 [1] sem_invalid(0x0), at 0xfec453ed [2] _sem_post(0x0), at 0xfec454c4 [3] PyThread_release_lock(0x0, 0xfe77ef2c, 0xfef43eba, 0x80c55c0, 0xfe77ef38, 0xfef441b5), at 0xfef492dc [4] PyEval_ReleaseLock(0x80c55c0, 0xfe77ef38, 0xfef441b5, 0xfeb12aec, 0xfe77ef70, 0xfeafb2e3), at 0xfef27abe [5] PyThreadState_DeleteCurrent(0xfeb12aec, 0xfe77ef70, 0xfeafb2e3, 0x1, 0x0, 0x80a3140), at 0xfef43eba [6] PyGILState_Release(0x1, 0x0), at 0xfef441b5 =>[7] Ticker::operator()(this = 0x810a304), line 28 in "ticker.cc" [8] boost::detail::thread_data<Ticker>::run(this = 0x810a288), line 56 in "thread.hpp" [9] thread_proxy(0x810a288), at 0xfea78ce4 [10] _thr_setup(0xfe670200), at 0xfee159b9 [11] _lwp_start(0xfe77ef08, 0xfec454c4, 0x0, 0xfe77ef54, 0x80c55c0, 0xfe77ef14), at 0xfee15ca0 "Paul Scruby" <p...@gingernut.tv> wrote in message news:h2sgic$ad...@ger.gmane.org... > Hiya, > > That's fantastic, all I needed to do was to put PyGILState_Ensure(); > before my virtual function calls into python from another thread and my > program no longer crashes. Problem solved, isn't boost::python great! > > Many thanks, > > Paul > > > "Renato Araujo" <rena...@gmail.com> wrote in message > news:95291a80907041315k41b7ad88o32d2111ae8fe1...@mail.gmail.com... > Hi Paul > > In my bindings I had a problem like this, to solve I created a simple > class like that: > > class thread_locker > { > thread_locker() > { > if (thread_support::enabled()) > m_gstate = PyGILState_Ensure(); > } > > ~thread_locker() > { > if (thread_support::enabled()) > PyGILState_Release(m_gstate); > } > }; > > then in my wrapper virtual implementation I did this: > > ... > void wrapper::virtual_func(..) > { > thread_locker lock; > .. my code .. > } > .... > > this solve my problems with call of virtual functions in thread > enviroment. > > BR > > > > > On Sat, Jul 4, 2009 at 5:03 PM, William Ladwig<wlad...@wdtinc.com> wrote: >> Whoops, I think this problem is a little uglier than I thought, since you >> overrode the onTick() function in python with a call to print, which >> needs access to the interpreter in your new thread. See the link Thomas >> posted for dealing with the GIL (along with worrying about any possible >> garbage collection issues). Now I remember why I kept my C++ threads >> isolated from Python stuff....sorry, it's been a while.... >> >> Bill >> ________________________________________ >> From: cplusplus-sig-bounces+wladwig=wdtinc....@python.org >> [cplusplus-sig-bounces+wladwig=wdtinc....@python.org] On Behalf Of >> William Ladwig [wlad...@wdtinc.com] >> Sent: Saturday, July 04, 2009 1:34 PM >> To: Development of Python/C++ integration >> Subject: Re: [C++-sig] boost::python and threads >> >> It looks to me like you have a garbage collection problem going on. If >> you create a wrapped c++ object in python, then python is going to own >> the object and will destroy it when its reference count goes to 0. In >> your python example script at the bottom, you call the Ticker's run() >> function, which from the python point of view, returns quickly and the >> script ends. Python has no idea that you spawned off a new thread from >> the C++ side, so when the script ends, python destroys the object and now >> you have a problem. One way that you can check to see if this is what is >> going on is to add this to the bottom of the test script and see if the >> crashes go away: >> >> # Warning, you'll need to kill this script manually >> import time >> while True: >> time.sleep(1) >> >> Generally when I want to fire off a new C++ thread, I hold any objects >> that the thread needs in an auto_ptr (see held type for class wrappers), >> take ownership of them in C++ (see the FAQ in the documentation) and >> start the thread from the C++ side. Or, you can also create C++ wrappers >> which accept shared_ptr arguments, while holding your classes in >> shared_ptrs, and this should handle the reference counting as well. >> Unfortunately, this may require some interface changes to what you have >> already written (or possibly some clever wrapping). >> >> Hope this helps, >> Bill >> >> >> ________________________________________ >> From: cplusplus-sig-bounces+wladwig=wdtinc....@python.org >> [cplusplus-sig-bounces+wladwig=wdtinc....@python.org] On Behalf Of Paul >> Scruby [p...@gingernut.tv] >> Sent: Friday, July 03, 2009 6:15 AM >> To: cplusplus-sig@python.org >> Subject: [C++-sig] boost::python and threads >> >> 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...@2 (l...@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...@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 >> >> >> >> _______________________________________________ >> Cplusplus-sig mailing list >> Cplusplus-sig@python.org >> http://mail.python.org/mailman/listinfo/cplusplus-sig >> _______________________________________________ >> Cplusplus-sig mailing list >> Cplusplus-sig@python.org >> http://mail.python.org/mailman/listinfo/cplusplus-sig >> _______________________________________________ >> Cplusplus-sig mailing list >> Cplusplus-sig@python.org >> http://mail.python.org/mailman/listinfo/cplusplus-sig >> > > > > -- > Renato Araujo Oliveira Filho _______________________________________________ Cplusplus-sig mailing list Cplusplus-sig@python.org http://mail.python.org/mailman/listinfo/cplusplus-sig