[C++-sig] boost::python and threads

2009-07-04 Thread Paul Scruby
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 
#include 
#include 

using namespace boost::python;

class Ticker
:public wrapper
{
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")
.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 0x0028(%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::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::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
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig


Re: [C++-sig] boost::python and threads

2009-07-06 Thread Paul Scruby
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"  wrote in message 
news:[email protected]...
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 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 stuffsorry, it's been a while
>
> Bill
> 
> From: [email protected] 
> [[email protected]] On Behalf Of William 
> Ladwig [[email protected]]
> 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: [email protected] 
> [[email protected]] On Behalf Of Paul 
> Scruby [[email protected]]
> Sent: Friday, July 03, 2009 6:15 AM
> To: [email protected]
> 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 
> #include 
> #include 
>
> using namespace boost::python;
>
> class Ticker
> : public wrapper
> {
> 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")
> .def("run&qu

Re: [C++-sig] boost::python and threads

2009-07-06 Thread Paul Scruby
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   0x0006(%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::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   0x0006(%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::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"  wrote in message 
news:[email protected]...
> 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"  wrote in message 
> news:[email protected]...
> 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 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 stuffsorry, it's been a while
>>
>> Bill
>> 
>> From: [email protected] 
>> [[email protected]] On Behalf Of 
>> William Ladwig [[email protected]]
>> Sent: Saturday, July 04, 2009 1:34 PM
>> To

[C++-sig] Passing Python classes derived from C++ back into C++

2009-07-07 Thread Paul Scruby
Hiya,

I'm trying to pass a C++ class that I've extended in Python to a C++ 
function.  I found an example of how to do this in David Abrahams article on 
Building Hybrid Systems with Boost Python.
http://www.boostpro.com/writing/bpl.html#virtual-functions

However, I've not managed to get this example to compile:

  #include 
  #include 
  using namespace boost::python;

  class Base
  {
   public:
  virtual int f(std::string x) { return 42; }
  virtual ~Base() {}
  };

  int calls_f(Base & b, std::string x) { return b.f(x); }

  struct BaseWrap : Base
  {
  BaseWrap(PyObject * self_) : self(self_) {}
  PyObject * self;
  int f_default(std::string x) { return this->Base::f(x); }
  int f(std::string x) { return call_method(self, "f", x); }
  };

  BOOST_PYTHON_MODULE(mytest)
  {
  def("calls_f", calls_f);
  class_("Base")
  .def("f", &Base::f, &BaseWrap::f_default);
  }

_

  from mytest import *

  class Derived(Base):
  def f(self, s):
  return len(s)

  calls_f(Base(), 'foo')
  calls_f(Derived(), 'forty-two')


With Boost 1.38 and Visual Studio 8 compiler I get the error:

  boost_1_38\boost\python\object\make_instance.hpp(68) : see reference to 
function template instantiation 
'boost::python::objects::value_holder_back_reference::value_holder_back_reference>(PyObject
 
*,A0)' being compiled
  with
  [
  Value=Base,
  Held=BaseWrap,
  T=const Base,
  A0=boost::reference_wrapper
  ]

With Boost 1.63 and Sun C++ 5.9 compiler I get the error:

  boost-1_36/boost/python/object/class_metadata.hpp", line 232:
  Error: Overloading ambiguity between "static 
boost::python::objects::class_metadata::maybe_register_pointer_to_python(void*, 
void*, void*)"
  and "static boost::python::objects::class_metadata::maybe_register_pointer_to_python(void*, 
void*, mpl_::bool_<1>*)".

I also tried extending the boost::python::wrapper using get_override() 
instead of call_method(), but as it can not be constructed with a 
PyObject * so the C++ base class can't be extracted from a Python 
derivation.

Has anyone managed to get this working?  Any help will be gratefully 
received.

Cheers,

Paul



___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig


Re: [C++-sig] Passing Python classes derived from C++ back into C++

2009-07-08 Thread Paul Scruby
Hi Rento,

Got it working now.  I did not realize that the wrapper<> automatically 
handled downcast conversion as well.

Thanks,

Paul

"Renato Araujo"  wrote in message 
news:[email protected]...
Hi Paul,

You can  extend from boost::python::wrapper  and use this function
to get PyObject from c++ object.
namespace detail
{
..
  namespace wrapper_base_ // ADL disabler
  {
inline PyObject* get_owner(wrapper_base const volatile& w);


BR



On Tue, Jul 7, 2009 at 7:54 AM, Paul Scruby wrote:
> Hiya,
>
> I'm trying to pass a C++ class that I've extended in Python to a C++
> function. I found an example of how to do this in David Abrahams article 
> on
> Building Hybrid Systems with Boost Python.
> http://www.boostpro.com/writing/bpl.html#virtual-functions
>
> However, I've not managed to get this example to compile:
>
> #include 
> #include 
> using namespace boost::python;
>
> class Base
> {
> public:
> virtual int f(std::string x) { return 42; }
> virtual ~Base() {}
> };
>
> int calls_f(Base & b, std::string x) { return b.f(x); }
>
> struct BaseWrap : Base
> {
> BaseWrap(PyObject * self_) : self(self_) {}
> PyObject * self;
> int f_default(std::string x) { return this->Base::f(x); }
> int f(std::string x) { return call_method(self, "f", x); }
> };
>
> BOOST_PYTHON_MODULE(mytest)
> {
> def("calls_f", calls_f);
> class_("Base")
> .def("f", &Base::f, &BaseWrap::f_default);
> }
>
> _
>
> from mytest import *
>
> class Derived(Base):
> def f(self, s):
> return len(s)
>
> calls_f(Base(), 'foo')
> calls_f(Derived(), 'forty-two')
>
>
> With Boost 1.38 and Visual Studio 8 compiler I get the error:
>
> boost_1_38\boost\python\object\make_instance.hpp(68) : see reference to
> function template instantiation
> 'boost::python::objects::value_holder_back_reference::value_holder_back_reference>(PyObject
> *,A0)' being compiled
> with
> [
> Value=Base,
> Held=BaseWrap,
> T=const Base,
> A0=boost::reference_wrapper
> ]
>
> With Boost 1.63 and Sun C++ 5.9 compiler I get the error:
>
> boost-1_36/boost/python/object/class_metadata.hpp", line 232:
> Error: Overloading ambiguity between "static
> boost::python::objects::class_metadata boost::python::detail::not_specified,
> boost::python::detail::not_specified>::maybe_register_pointer_to_python(void*,
> void*, void*)"
> and "static boost::python::objects::class_metadata boost::python::detail::not_specified,
> boost::python::detail::not_specified>::maybe_register_pointer_to_python(void*,
> void*, mpl_::bool_<1>*)".
>
> I also tried extending the boost::python::wrapper using get_override()
> instead of call_method(), but as it can not be constructed with a
> PyObject * so the C++ base class can't be extracted from a Python
> derivation.
>
> Has anyone managed to get this working? Any help will be gratefully
> received.
>
> Cheers,
>
> Paul
>
>
>
> ___
> Cplusplus-sig mailing list
> [email protected]
> http://mail.python.org/mailman/listinfo/cplusplus-sig
>



-- 
Renato Araujo Oliveira Filho 



___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig


Re: [C++-sig] boost::python and threads

2009-07-08 Thread Paul Scruby
Hi Renato,

Okay, I have installed Python 2.4.2 with gcc 4.1.2 on Linux and it's 
crashing in the same place as on Solaris.

  Program received signal SIGSEGV, Segmentation fault.
  [Switching to Thread 0x41074940 (LWP 12004)]
  0x00307740c850 in sem_post () from /lib64/libpthread.so.0
  (gdb) where
  #0  0x00307740c850 in sem_post () from /lib64/libpthread.so.0
  #1  0x00308b2b78e9 in PyThread_release_lock ()
 from /usr/lib64/libpython2.4.so.1.0
  #2  0x2b46531d9f82 in Ticker::operator() (this=0xbd0f478) at 
ticker.cc:28
  #3  0x2b46531d9fb0 in boost::detail::thread_data::run (
  this=0xbd0f370)
  at /opt/atm/include/boost-1_39/boost/thread/detail/thread.hpp:56
  #4  0x2b46533ee14b in thread_proxy ()
 from /opt/atm/lib64/libboost_thread-gcc41-mt-1_39.so.1.39.0
  #5  0x003077406367 in start_thread () from /lib64/libpthread.so.0
  #6  0x0030768d2f7d in clone () from /lib64/libc.so.6

With the global interpret lock added my code now looks like this...

  #include 
  #include 
  #include 
  using namespace boost::python;

  class Ticker
  :public wrapper
  {
  private:
  bool run_;
  volatile bool * running_;
  boost::thread * thread_;
  boost::xtime xt_;
  PyGILState_STATE state_;
  public:
  Ticker() :running_(&run_) { *running_ = false; }

  void operator()()
  {
  while (*running_)
  {
  boost::xtime_get(&xt_, boost::TIME_UTC);
  ++xt_.sec;
  boost::thread::sleep(xt_);
  state_ = PyGILState_Ensure();
  onTick();
  PyGILState_Release(state_);
  }
  }

  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")
  .def("run", &Ticker::run)
  .def("stop", &Ticker::stop)
  .def("onTick", &Ticker::default_onTick);
  }


Thanks again,

Paul


"Renato Araujo"  wrote in message 
news:[email protected]...
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 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
> t...@2 (l...@2) signal SEGV (no mapping at the fault address) in sem_invalid
> at 0xfec453ed
> 0xfec453ed: sem_invalid+0x0013: movzwl 0x0006(%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::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 0x0006(%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, 0xfe77ef2

Re: [C++-sig] boost::python and threads

2009-07-09 Thread Paul Scruby
Hi Renato,

It's all working now, tested on gcc, sun C++ and visual studio.

Thanks again,

Paul


"Renato Araujo"  wrote in message 
news:[email protected]...
Ok I made 2 modifications and I got this working here.

Try this.

51,54c50
<  virtual void onTick() {
<  if (object o = get_override("onTick"))
<  o();
<   }
---
>  virtual void onTick() { get_override("onTick")(); }
60d55
<  PyEval_InitThreads();
65a61
>

BR




On Wed, Jul 8, 2009 at 12:48 PM, Paul Scruby wrote:
> Hi Renato,
>
> Okay, I have installed Python 2.4.2 with gcc 4.1.2 on Linux and it's
> crashing in the same place as on Solaris.
>
> Program received signal SIGSEGV, Segmentation fault.
> [Switching to Thread 0x41074940 (LWP 12004)]
> 0x00307740c850 in sem_post () from /lib64/libpthread.so.0
> (gdb) where
> #0 0x00307740c850 in sem_post () from /lib64/libpthread.so.0
> #1 0x00308b2b78e9 in PyThread_release_lock ()
> from /usr/lib64/libpython2.4.so.1.0
> #2 0x2b46531d9f82 in Ticker::operator() (this=0xbd0f478) at
> ticker.cc:28
> #3 0x2b46531d9fb0 in boost::detail::thread_data::run (
> this=0xbd0f370)
> at /opt/atm/include/boost-1_39/boost/thread/detail/thread.hpp:56
> #4 0x2b46533ee14b in thread_proxy ()
> from /opt/atm/lib64/libboost_thread-gcc41-mt-1_39.so.1.39.0
> #5 0x003077406367 in start_thread () from /lib64/libpthread.so.0
> #6 0x0030768d2f7d in clone () from /lib64/libc.so.6
>
> With the global interpret lock added my code now looks like this...
>
> #include 
> #include 
> #include 
> using namespace boost::python;
>
> class Ticker
> : public wrapper
> {
> private:
> bool run_;
> volatile bool * running_;
> boost::thread * thread_;
> boost::xtime xt_;
> PyGILState_STATE state_;
> public:
> Ticker() :running_(&run_) { *running_ = false; }
>
> void operator()()
> {
> while (*running_)
> {
> boost::xtime_get(&xt_, boost::TIME_UTC);
> ++xt_.sec;
> boost::thread::sleep(xt_);
> state_ = PyGILState_Ensure();
> onTick();
> PyGILState_Release(state_);
> }
> }
>
> 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")
> .def("run", &Ticker::run)
> .def("stop", &Ticker::stop)
> .def("onTick", &Ticker::default_onTick);
> }
>
>
> Thanks again,
>
> Paul
>
>
> "Renato Araujo"  wrote in message
> news:[email protected]...
> 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 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
>> t...@2 (l...@2) signal SEGV (no mapping at the fault address) in sem_invalid
>> at 0xfec453ed
>> 0xfec453ed: sem_invalid+0x0013: movzwl 0x0006(%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::run(this = 0x810a288), line 56
>> in "thread.hpp"
>> [9] thread_proxy(0x810a288), at 0xfea78ce4
>> [10] _thr_setup(0xfe6