Calling a SWIG director method from C++ thread crashes Python interpreter

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Calling a SWIG director method from C++ thread crashes Python interpreter

Leonardo
This post has NOT been accepted by the mailing list yet.
Hi everyone,
I've got an issue related to race conditions in the Python interpreter when a director method is called from within a C++ thread (not the one that started the Python interpreter).
I found a solution which was locking the GIL in the director method but I cannot automatize this process since I have no access to the point where SWIG generates the director code. I've tried for instance modifying the code below via %typemap(directorin) but wasn't successful since I just can add an instance of GIL_locker AFTER the swig::SwigVar_PyObject obj0; statement, not before it (note that obj0 should be created after the lock object for it uses the Python interpreter for object destruction).

class GIL_locker {
public:
  GIL_locker()
    : gstate(PyGILState_Ensure())
  {}

  ~GIL_locker()
  {
    PyGILState_Release(gstate);
  }
private:
  PyGILState_STATE gstate;
};


void SwigDirector_session_subscriber::on_element_updated(smh::element_ptr updated) {
  //  GIL_locker lock;  ====> That's where GIL should be locked, just BEFORE obj0 is created!
  swig::SwigVar_PyObject obj0;
  obj0 = SWIG_NewPointerObj(SWIG_as_voidptr(new smh::element_ptr((const smh::element_ptr &)updated)), SWIGTYPE_p_boost__shared_ptrT_smh__element_t, SWIG_POINTER_OWN |  0 );
  if (!swig_get_self()) {
    Swig::DirectorException::raise("'self' uninitialized, maybe you forgot to call session_subscriber.__init__.");
  }
#if defined(SWIG_PYTHON_DIRECTOR_VTABLE)
  const size_t swig_method_index = 4;
  const char *const swig_method_name = "on_element_updated";
  PyObject *method = swig_get_method(swig_method_index, swig_method_name);
  swig::SwigVar_PyObject result = PyObject_CallFunction(method, (char *)"(O)" ,(PyObject *)obj0);
#else
  swig::SwigVar_PyObject result = PyObject_CallMethod(swig_get_self(), (char *)"on_element_updated", (char *)"(O)" ,(PyObject *)obj0);
#endif
  if (!result) {
    PyObject *error = PyErr_Occurred();
    {
      if (error != NULL) {
        throw Swig::DirectorMethodException();
      }
    }
  }
}

Thanks!
Loading...