I’m currently having some trouble with a finalizer cleaning up an object that is needed by another finalizer.
I have two objects, both of which contain pointers to some C object, one of which is a “context object” for the other (contains some information needed to clean the other up).
The first object R has a type that looks like this:
type SingularPolyRing ptr::some_c_thing1 end
The second object p say, has a type that looks like this:
type spoly ptr::some_c_thing2 parent::SingularPolyRing function spoly(R::SingularPolyRing, p::some_c_thing2) z = new(p, R) finalizer(z, _spoly_cleanup) return z end end
(Here _spoly_cleanup(z) calls some C function to clean up.)
Both objects have finalizers, but when julia is shut down, the finalizer for the first object R is always called before that of the second, even though the second object p contains a reference to the first object R!
I tried writing the finalizer for the spoly p as follows:
function spoly(R::SingularPolyRing, p::some_c_thing2) z = new(some_c_thing2, R) finalizer(z, x -> _spoly_clear_fn(x, R)) return z end
The reasoning is that surely the lambda/closure hangs onto a copy of R, preventing it from being cleaned up first. But alas, R is still cleaned up first, before
_spoly_clear_fn gets called. I’ve verified this by putting print statements in the relevant C functions.
Is there a canonical way of preventing Julia from cleaning up an object that is needed to clean up another object?