Finalizers not running


#1

I’m having some trouble getting finalizers to run, it seems that in some cases finalizers are only run atexit, and not when the object seems unreachable and I’ve called gc() a couple of times.

For example, the following snippet works as expected:

type Foo
    field
    function Foo()
        obj = new(1)
        finalizer(obj, finalize)
        return obj
    end
end

finalized = false
function finalize(obj::Foo)
    global finalized
    finalized = true
    msg = "Finalizing...\n"
    ccall(:write, Cssize_t, (Cint, Cstring, Csize_t),
          1, msg, length(msg))
end

let
    foo = Foo()
end

println("Forcing GC")
for i in 1:10
    gc()
end
@assert finalized

However, if I change Foo not to have any fields, the finalizer isn’t run before the program exits:

type Foo
    function Foo()
        obj = new()
        finalizer(obj, finalize)
        return obj
    end
end

...

ERROR: LoadError: AssertionError: finalized
Finalizing...

Another one, again starting from the top example from this post (ie. with field) but this time throwing a MethodError refering to an instance of foo:

let
    foo = Foo()
    @test_throws MethodError sin(foo)
end

...

ERROR: LoadError: AssertionError: finalized
Finalizing...

Are these genuine bugs, or am I expecting something from the gc which it can’t/doesn’t guarantee?

cc @yuyichao


#2

Objects without fields (otherwise known as singletons) are never allocated, so they never need to be freed.


#3

I suspected it would be something like that. The second issue is the realistic one though, where GPU array finalizers aren’t run and hence memory isn’t freed.


#4

I’m guessing that @test_throws is creating a new function (rather than a closure) over the variable foo since it sees that it is as the toplevel scope. This is perhaps a lowering bug, but one that exists for compatibility with existing code.


#5

For the second case, it was kept alive in exception_in_transit.


#6

Ah, yes, I had just reduced it to throw(foo)… Thanks.


#7

ah, ok, so it is a bug (submitted https://github.com/JuliaLang/julia/issues/20784)