I'm using gcc/linux and python >= 2.4 and works fine for me.
On Mon, Jul 6, 2009 at 7:39 AM, Paul Scruby<p...@gingernut.tv> wrote: > 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 > �...@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 > -- Renato Araujo Oliveira Filho _______________________________________________ Cplusplus-sig mailing list Cplusplus-sig@python.org http://mail.python.org/mailman/listinfo/cplusplus-sig