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?