On Sunday, May 7, 2017 at 8:21:38 AM UTC-7, Bruno Albuquerque wrote: > > I have this struct that has an associated method that simply call a C > function that might take a long time to use. It is defined more or less > like this: > > import "C" > > type Indexer struct { > cIndexer *C.Indexer > } > > func NewIndexer() *Indexer { > i := &Indexer{getCIndexerPointer()} > runtime.SetFinalizer(i, (*Indexer).finalize) > } > > func (i *Indexer) finalize() { > freeCIndexertPointer(i.cIndexer) > } > > func (i *Indexer) Commit() { > callCCommit(i.cIndexer) > } > > Then I have some code that uses an indexer object: > > func Index() { > i := NewIndexer() > > // Index documents calling Indexer methods. > > i.Commit() > } > > For some corpus, the Commit() call above might take several minutes to > complete. It looks like that if the garbage collector kicks in when it is > running, the runtime thinks that it is ok to collect the object and this > triggers the finalizer that, in turn, deletes the internal C object that, > finally, make the C commit call to crash as the C struct it uses to do its > job was freed. > > I am aware that a call to runtime.KeepAlive(i) after the Commit() call > should be enough to sort this up, but I am wondering why it is required at > all in this case. Isn't the fact that a method on a struct type is running > enough to avoid collection? >
No. Method arguments are no different from regular arguments. In your Commit method, i is not live after the call to callCCommit. So as far as the live variable analysis is concerned, i is dead during the call. > If not, shouldn't it be? > It used to be. Before Go 1.7, we used to keep all arguments alive throughout the function. It was kind of a hack, mostly to work around the lack of something like runtime.KeepAlive. Keeping arguments live throughout the function often lead to objects being retained longer than necessary (the opposite problem from what you are observing). We didn't see a way to solve this problem automatically. We decided to use the minimal live ranges and provide runtime.KeepAlive so you can extend the live range. I think the other direction (keeping the longer live ranges and providing a runtime.AssertThisIsDead) wouldn't work. > Or is this related to the usage of CGO? > > It often comes up in the context of CGO and finalizers, but this behavior can be observed in other contexts. > In any case, it was a bit unexpected to me (although I did guess that the > problem was this and adding debug to the finalizer helped confirming it). I > would go as far as to say this looks like a bug. > > Thoughts? > > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.