Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

`except +` is ignored for C++ class member constructor #3165

navytux opened this issue Oct 3, 2019 · 0 comments


Copy link

commented Oct 3, 2019

Hello up there. I've found that except + clause, if it is used on C++ class contructur, is ignored in generated cinit if that class is used as data member of a Python class. The following example demonstrates the problem:

---- 8< ---- (x.pyx)

# cython: language_level=2
# distutils: language=c++

cdef extern from *:
    #include <exception>

    struct MyClass {
        MyClass() { throw std::bad_alloc(); }        
    cppclass MyClass:
        MyClass() except +

cdef class PyClass:
    cdef MyClass my_class

def test():
    obj = PyClass()
$ cythonize -i x.pyx
$ python -c 'import x; x.test()'
terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc

Generated tp_new for PyClass is below:

static PyObject *__pyx_tp_new_1x_PyClass(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) {
  struct __pyx_obj_1x_PyClass *p;
  PyObject *o;
  if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) {
    o = (*t->tp_alloc)(t, 0);
  } else {
    o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0);
  if (unlikely(!o)) return 0;
  p = ((struct __pyx_obj_1x_PyClass *)o);
  new((void*)&(p->my_class)) MyClass();
  return o;

It indeed calls MyClass constructor and does not wrap it with try/catch to translate C++ exceptions into Python ones (the new((void*)&(p->my_class)) MyClass(); line).

Cython version: 0.29.13-580-g074362b47 (today's master)

Thanks beforehand,

/cc @scoder, @robertwb

navytux added a commit to navytux/pygolang that referenced this issue Oct 4, 2019
Until now libgolang had semaphore and mutex functionality, but
implemented only internally and not exposed to users. Since for its
pinner thread wendelin.core v2 needs not only nogil channels, but also
nogil mutexes, timers and so on, it is now time to start providing that.

We start with mutexes:

- Expose Mutex from insides of libgolang.cpp to public API in
  libgolang.h . We actually expose both Mutex and Sema because
  semaphores are sometimes also useful for low-level synchronization,
  and because it is easier to export Mutex and Sema both at the same time.

- Provide pyx/nogil API to those as sync.Mutex and sync.Sema.

- Provide corresponding python wrappers.

- Add Pyx-level test for semaphore wakeup when wakeup is done not by the
  same thread which did the original acquire. This is the test that was
  promised in 5142460 (libgolang/thread: Add links to upstream
  PyThread_release_lock bug), and it used to corrupt memory and deadlock
  on macOS due to CPython & PyPy runtime bugs:
      -> python/cpython#16047

Note about python wrappers: At present, due to
cython/cython#3165, C-level panic is not
properly translated into Py-level exception in (Py)Sema/Mutex constructors.
This should not pose a real problem in practice though.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
1 participant
You can’t perform that action at this time.