Skip to content

runtime: Finalizer not called for parent variable #6268

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
lukescott opened this issue Aug 28, 2013 · 7 comments
Closed

runtime: Finalizer not called for parent variable #6268

lukescott opened this issue Aug 28, 2013 · 7 comments

Comments

@lukescott
Copy link

Run this code:

http://play.golang.org/p/Ma-dZ5_Kqp

What is the expected output?

bar collected
foo collected

What do you see instead?

bar collected

Which compiler are you using (5g, 6g, 8g, gccgo)?

go (default)

Which operating system are you using?

Mac OS X 10.8.4

Which version are you using?  (run 'go version')

go version go1.1.1 darwin/amd64
go version devel +21a81bde7dc9 Wed Aug 28 09:40:08 2013 +1000 darwin/amd64

Please provide any additional information below.

I may be doing something wrong. But I would expect both "Foo" and
"Bar" finalizers to be called.

If you comment out line #33 it works and you get:

foo collected
bar collected

But then the values are no longer associated, and the order is wrong.

I'm using Finalizers to clean up memory on the heap in C/C++. I wrap a C pointer in a Go
struct.
@ianlancetaylor
Copy link
Member

Comment 1:

The runtime makes no guarantee that finalizers are ever called.  They are only
best-effort.
Fortunately, your program does work on tip: both finalizers are run.  I expect that this
is due to improvements in the garbage collector.

Status changed to WorkingAsIntended.

@lukescott
Copy link
Author

Comment 2:

Um, if I do runtime.GC(), wouldn't they meant the finalizes should always run?
I tried running it on tip and I hit the same result.

@ianlancetaylor
Copy link
Member

Comment 3:

The garbage collector is not perfectly precise.  It is conservative.  That means that in
some cases it will retain a block that is not really being referenced.  There is ongoing
work to improve this.
I'm not sure why you are seeing a different result on tip than I am.  I ran your test
case on a GNU/Linux system.

@lukescott
Copy link
Author

Comment 4:

In what cases would this happen, even when runtime.GC() is called?
I re-ran it on tip, and it's working now. Strange. 
I am having some odd results with cgo though that's causing the finalizer not to run.
Specifically I have a C struct inside my Go struct, and when V8 does a TryCatch my
Isolate finalizer isn't run. Still debugging this.

@davecheney
Copy link
Contributor

Comment 5:

> In what cases would this happen, even when runtime.GC() is called?
To reiterate what Iant said, finalisers are not guaranteed to run. Calling runtime.GC
does not change this statement, nor influence the non guarantee that finalisers will be
ever be called.

@lukescott
Copy link
Author

Comment 6:

Forgive me, but in quoting the docs:
>If a cyclic structure includes a block with a finalizer, that cycle is not guaranteed
to be garbage collected and the finalizer is not guaranteed to run, because there is no
ordering that respects the dependencies.
So if I don't have a cyclic structure, it should always run.
> There is no guarantee that finalizers will run before a program exits, so typically
they are useful only for releasing non-memory resources associated with an object during
a long-running program.
If I run runtime.GC, this runs the garbage collector before the program exits.
With what I'm doing I don't have a cyclic structure, and the garbage collector is
running before the program exits.
So what else is not guaranteed, besides what is mentioned in the docs? I know I am
having some weird behavior with cgo.

@davecheney
Copy link
Contributor

Comment 7:

@luke. runtime.GC() does not provide a guarentee that a finaliser will run. I can see
how it could be construed that that if the object is not garbage collected the finaliser
cannot run, however runtime.GC() does not currently guarentee that all memory that can
be collected will be collected (see comment #3), and even if the memory was collected,
it is not guarenteed that the finaliser will not be run, because no such guarentee is
made.
Please, let's not talk about runtime.GC has having anything to do with this issue.

@golang golang locked and limited conversation to collaborators Jun 25, 2016
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants