1 | """ |
---|
2 | >>> x = SimpleGarbage() |
---|
3 | SimpleGarbage(1) __cinit__ |
---|
4 | >>> del x |
---|
5 | SimpleGarbage(1) __dealloc__ |
---|
6 | Collector.__dealloc__ |
---|
7 | collect 0 |
---|
8 | """ |
---|
9 | |
---|
10 | import gc, sys, weakref |
---|
11 | |
---|
12 | cdef int counter = 0 |
---|
13 | cdef int next_counter(): |
---|
14 | global counter |
---|
15 | counter += 1 |
---|
16 | return counter |
---|
17 | |
---|
18 | cdef class Collector: |
---|
19 | # Indirectly trigger garbage collection in SimpleGarbage deallocation. |
---|
20 | # The __dealloc__ method of SimpleGarbage won't trigger the bug as the |
---|
21 | # refcount is artifitially inflated for the durration of that function. |
---|
22 | def __dealloc__(self): |
---|
23 | print "Collector.__dealloc__" |
---|
24 | print "collect", gc.collect() |
---|
25 | |
---|
26 | cdef class SimpleGarbage: |
---|
27 | cdef Collector c # to particpate in garbage collection |
---|
28 | cdef int index |
---|
29 | cdef bint deallocated |
---|
30 | def __cinit__(self): |
---|
31 | self.index = next_counter() |
---|
32 | self.c = Collector() |
---|
33 | print self, "__cinit__" |
---|
34 | def __dealloc__(self): |
---|
35 | print self, "__dealloc__" |
---|
36 | if self.deallocated: |
---|
37 | print "Double dealloc!" |
---|
38 | self.deallocated = True |
---|
39 | gc.collect() |
---|
40 | def __str__(self): |
---|
41 | return "SimpleGarbage(%s)" % self.index |
---|
42 | def __repr__(self): |
---|
43 | return "SimpleGarbage(%s)" % self.index |
---|