Skip to content

runtime: finalizers keep data live for a surprising amount of time #5348

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
neild opened this issue Apr 24, 2013 · 10 comments
Closed

runtime: finalizers keep data live for a surprising amount of time #5348

neild opened this issue Apr 24, 2013 · 10 comments

Comments

@neild
Copy link
Contributor

neild commented Apr 24, 2013

What steps will reproduce the problem?
1. http://play.golang.org/p/G8in4BHWr-
2. Build with -ldflags=-Z  (note that you can't reproduce this on play)

What is the expected output?
Hello, playground
GC T
GC string
Goodbye, playground

What do you see instead?
Hello, playground
GC T
Goodbye, playground

The string is never GC'd.  However, if you remove the finalizer from the struct, the
string *is* GC'd.

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

Which operating system are you using?
Linux

Which version are you using?  (run 'go version')
go version devel +62bf913b4f40 Wed Feb 27 20:55:01 2013 -0800 linux/amd64

Please provide any additional information below.
Adding a "*(void**)frame = 0" just after the reflect.call in runfinq() results
in the string being GC'd on the next GC pass.  If I'm right, this limits the data held
artificially live to a single object.
@bradfitz
Copy link
Contributor

Comment 1:

Labels changed: removed priority-triage.

Status changed to Accepted.

@bradfitz
Copy link
Contributor

Comment 3:

Carl theorized that this was related to his work on issue #353 & issue #5134.
To test that theory, he was curious to see what happened if you ran foo in a goroutine,
with its own stack.
No change:
$ cat z.go
package main
import (
        "fmt"
        "runtime"
)
type T struct {
        S *string
}
func newString(s string) *string {
        return &s
}
func foo() {
        t := &T{S: newString("foo")}
        runtime.SetFinalizer(t, func(p *T) { fmt.Println("GC T") })
        runtime.SetFinalizer(t.S, func(p *string) { fmt.Println("GC string") })
}
func main() {
        fmt.Println("hi")
    donec := make(chan bool)
    go func() {
        foo()
        donec <- true
    }()
    <-donec
        runtime.GC()
        runtime.GC()
        fmt.Println("bye")
}
$ go run --ldflags=-Z z.go
hi
GC T
bye
Likewise if making the channel buffered or putting in a big sleep after the channel
receive.

@neild
Copy link
Contributor Author

neild commented Apr 24, 2013

Comment 4:

hi
GC T
bye
With the attached patch, however:
hi
GC T
GC string
bye

@bradfitz
Copy link
Contributor

Comment 5:

No patch is attached.
In general we don't use issue tracker attachments for patches, though... for CLA and
reviewability reasons. If we use rietveld, then others can patch in your patch easily
with "hg clpatch NNNNNN". But you're aware of http://golang.org/doc/contribute.html

@gopherbot
Copy link
Contributor

Comment 7:

Corrected source code with predictable behavior: http://play.golang.org/p/nC4wJ5hapl

@gopherbot
Copy link
Contributor

Comment 8:

This issue was closed by revision e9bbe3a.

Status changed to Fixed.

@gopherbot
Copy link
Contributor

Comment 9:

This issue was closed by revision db1c218.

@gopherbot
Copy link
Contributor

Comment 10:

Status changed to LongTerm.

@bradfitz
Copy link
Contributor

Comment 11:

Labels changed: added priority-later.

Status changed to Accepted.

@dvyukov
Copy link
Member

dvyukov commented Jul 19, 2013

Comment 12:

This issue was closed by revision eb04df7.

Status changed to Fixed.

@golang golang locked and limited conversation to collaborators Jun 24, 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