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

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

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 {
    : gstate(PyGILState_Ensure())

  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__.");
  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);
  swig::SwigVar_PyObject result = PyObject_CallMethod(swig_get_self(), (char *)"on_element_updated", (char *)"(O)" ,(PyObject *)obj0);
  if (!result) {
    PyObject *error = PyErr_Occurred();
      if (error != NULL) {
        throw Swig::DirectorMethodException();