question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Broken scikit-image build with 3.0a3 : redeclaration of ‘__pyx_gilstate_save’ with no linkage

See original GitHub issue

The scikit-image pre builds is broken since Cython 3.0a3 was released yesterday.

The error is as follows:

skimage/graph/heap.c: In function ‘__pyx_f_7skimage_5graph_4heap_10BinaryHeap__add_or_remove_level’:
skimage/graph/heap.c:3299:20: error: redeclaration of ‘__pyx_gilstate_save’ with no linkage
   PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
                    ^~~~~~~~~~~~~~~~~~~
skimage/graph/heap.c:3296:20: note: previous declaration of ‘__pyx_gilstate_save’ was here
   PyGILState_STATE __pyx_gilstate_save;
                    ^~~~~~~~~~~~~~~~~~~

corresponding to this part of heap.pyx (https://github.com/scikit-image/scikit-image/blob/master/skimage/graph/heap.pyx#L190)

cdef void _add_or_remove_level(self, LEVELS_T add_or_remove) nogil:
        # init indexing ints
        cdef INDEX_T i, i1, i2, n

        # new amount of levels
        cdef LEVELS_T new_levels = self.levels + add_or_remove

        # allocate new arrays
        cdef INDEX_T number = 2**new_levels
        cdef VALUE_T *values
        cdef REFERENCE_T *references
        values = <VALUE_T *>malloc(number * 2 * sizeof(VALUE_T))
        references = <REFERENCE_T *>malloc(number * sizeof(REFERENCE_T))
        if values is NULL or references is NULL:
            free(values)
            free(references)
            with gil:
                raise MemoryError()

When I compare the generated C code with 3.0a1 and 3.0a2, only these part changed 3.0a1

#ifdef WITH_THREAD
PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
#endif

and 3.0a3

#ifdef WITH_THREAD
PyGILState_STATE __pyx_gilstate_save;
#endif
#ifdef WITH_THREAD
PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
#endif

so indeed __pyx_gilstate_save is defined twice.

Any advice about what is going on will be much appreciated 😃.

If it helps, here is a bit more of the C code (for 3.0a3):

static void __pyx_f_7skimage_5graph_4heap_10BinaryHeap__add_or_remove_level(struct __pyx_obj_7skimage_5graph_4heap_BinaryHeap *__pyx_v_self, __pyx_t_7skimage_5graph_4heap_LEVELS_T __pyx_v_add_or_remove) {
  __pyx_t_7skimage_5graph_4heap_INDEX_T __pyx_v_i;
  __pyx_t_7skimage_5graph_4heap_INDEX_T __pyx_v_i1;
  __pyx_t_7skimage_5graph_4heap_INDEX_T __pyx_v_i2;
  __pyx_t_7skimage_5graph_4heap_INDEX_T __pyx_v_n;
  __pyx_t_7skimage_5graph_4heap_LEVELS_T __pyx_v_new_levels;
  __pyx_t_7skimage_5graph_4heap_INDEX_T __pyx_v_number;
  __pyx_t_7skimage_5graph_4heap_VALUE_T *__pyx_v_values;
  __pyx_t_7skimage_5graph_4heap_REFERENCE_T *__pyx_v_references;
  __pyx_t_7skimage_5graph_4heap_VALUE_T *__pyx_v_old_values;
  __pyx_t_7skimage_5graph_4heap_REFERENCE_T *__pyx_v_old_references;
  __Pyx_RefNannyDeclarations
  int __pyx_t_1;
  int __pyx_t_2;
  __pyx_t_7skimage_5graph_4heap_INDEX_T __pyx_t_3;
  __pyx_t_7skimage_5graph_4heap_INDEX_T __pyx_t_4;
  __pyx_t_7skimage_5graph_4heap_INDEX_T __pyx_t_5;
  __pyx_t_7skimage_5graph_4heap_VALUE_T *__pyx_t_6;
  __pyx_t_7skimage_5graph_4heap_REFERENCE_T *__pyx_t_7;
  #ifdef WITH_THREAD
  PyGILState_STATE __pyx_gilstate_save;
  #endif
  #ifdef WITH_THREAD
  PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
  #endif
  __Pyx_RefNannySetupContext("_add_or_remove_level", 0);
  #ifdef WITH_THREAD
  __Pyx_PyGILState_Release(__pyx_gilstate_save);
  #endif

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

3reactions
scodercommented, Apr 28, 2020

Note, BTW, that the method signature prevents exception propagation: cdef void _add_or_remove_level(self, LEVELS_T add_or_remove) nogil: Instead, either change the return type from void to something else, e.g. int (with except -1 or similar), or declare the method as except * to make the caller always check for exceptions.

Oh, and the with gil: is no longer required for the raise since 0.29. It’s injected automatically when raise is used in a nogil section.

0reactions
scodercommented, Apr 29, 2020

Cython generates a warning here, but with warning level 0, i.e. it’s normally invisible. Setting Cython.Compiler.Errors.LEVEL = 0 will show it. (I guess there should be a better interface to that, preferably a keyword argument in cythonize()).

Read more comments on GitHub >

github_iconTop Results From Across the Web

No results found

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found