[Cython] Generators not closed on dealloc (Cython 0.15.1+, current git master)

Matt Hagy hagy at gatech.edu
Sun Nov 13 20:51:23 CET 2011


Hi,

Cython generators aren’t closed on dealloc and this can lead to cleanup code not being ran (see example below). I couldn’t find any reference to this issue on the trac or the wiki and therefore wanted to report it. If this is a know issue please disregard this post.

I believe this can easily be corrected by adding the following line to the top of each generator dealloc function:

    if (p->resume_label != -1) __Pyx_Generator_Close(o);

This explicitly closes the generator unless it’s already finished. For testing I manually added this code to the generated C file and it worked as expected.

-Matt

Example:

I found this issue in the following code that relies upon a finally block to free memory. If not explicitly closed, the cleanup code is never executed and memory is leaked.

############################################
# generate_primes.pyx

from libc.stdlib cimport malloc, realloc, free

def generate_primes(unsigned int initial_buffer_size=64):
    cdef unsigned int test_number, i, N_primes, N_allocated
    cdef unsigned int *primes

    N_primes = 0
    N_allocated = initial_buffer_size
    primes = <unsigned int*>malloc(N_allocated * sizeof(unsigned int))
    if not primes: raise MemoryError

    test_number = 2

    try:
        while 1:
            # is the current value of test_number prime?
            # i.e. is it not divisible by any of the already seen primes
            i = 0
            while i<N_primes and test_number % primes[i] != 0:
                i += 1

            if i == N_primes:
                yield test_number

                # grow primes array if needed
                if N_primes == N_allocated:
                    N_allocated = N_allocated + 64
                    primes = <unsigned int*>realloc(primes, N_allocated * sizeof(unsigned int))
                    if not primes: raise MemoryError

                primes[N_primes] = test_number
                N_primes += 1

            test_number += 1
    finally:
        print 'clean up'
        free(primes)

###############################################


More information about the cython-devel mailing list