-
Notifications
You must be signed in to change notification settings - Fork 321
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
Double free error when cloning repository #98
Comments
It deallocates it on error, because it doesn't return it. If there's an error, it's something else. |
I see, What is interesting, though, is that my double free error went away when I commented the finalizer. I will keep digging more anyway. |
It also goes away if I change this: func (v *Repository) Free() {
runtime.SetFinalizer(v, nil)
C.git_repository_free(v.ptr)
} to
I agree the real culprit is still unknown. I'm going to check next if the finalizer is being called more than once by Go. |
After some more testing, it is now looking more like a race condition somewhere inside git2go. This is what I'm doing, I'm starting multiple goroutines at once, each one cloning a different repository. I wait for all of them to finish and return back the result. It sometimes finishes fine and sometimes it is not. |
Or maybe I'm misusing git2go? This is what I'm doing: log.Info("Downloading buildpacks...")
for _, bp := range bpacks {
wg.Add(1)
go func(url string) {
log.Info("Cloning " + url + " into " + bpacksPath)
defer wg.Done()
parts := strings.Split(url, "#")
branch := "master"
if len(parts) == 2 {
branch = parts[1]
}
dest := filepath.Join(bpacksPath, path.Base(url))
options := &git.CloneOptions{
CheckoutBranch: branch,
}
_, err := git.Clone(url, dest, options)
if err != nil {
log.Error(err.Error())
}
}(bp)
}
wg.Wait() |
That definitely looks like it should work. The check for |
I also tested checking for |
That trace you posted says it goes through |
Sorry, I should have mentioned that before, I'm using your |
Ok, that has the same clone code. I can't reproduce locally with code that should behave the same, but with more fixed data. I had added a line to the imports, so of course line 48 is the actual package main
import (
"io/ioutil"
"sync"
"log"
"github.com/libgit2/git2go"
"runtime"
)
func main() {
list := []string {
"git://localhost/git/git-httpd",
"git://localhost/git/git-httpd",
"git://localhost/git/git-httpd",
"git://localhost/git/git-httpd",
"git://localhost/git/git-httpd",
"git://localhost/git/git-httpd",
"git://localhost/git/git-httpd",
"git://localhost/git/git-httpd",
"git://localhost/git/git-httpd",
"git://localhost/git/git-httpd",
"git://localhost/git/git-httpd",
"git://localhost/git/git-httpd",
}
var wg sync.WaitGroup
for _, repo := range list {
wg.Add(1)
go func(url string) {
defer wg.Done()
path, err := ioutil.TempDir("", "clone-test-clone")
if err != nil {
log.Fatal(":(", err)
}
opts := &git.CloneOptions{
CheckoutBranch: "master",
}
_, err = git.Clone(url, path, opts)
if err != nil {
log.Println(" -- ", err)
}
}(repo)
}
wg.Wait()
runtime.GC()
} |
These are the URLs I'm using: var buildpacks = []string{
//Heroku official buildpacks
"https://github.com/heroku/heroku-buildpack-play.git",
"https://github.com/heroku/heroku-buildpack-scala.git",
"https://github.com/heroku/heroku-buildpack-java.git",
"https://github.com/heroku/heroku-buildpack-ruby.git",
"https://github.com/heroku/heroku-buildpack-nodejs.git",
"https://github.com/heroku/heroku-buildpack-python.git",
"https://github.com/heroku/heroku-buildpack-clojure.git",
"https://github.com/heroku/heroku-buildpack-gradle.git",
"https://github.com/heroku/heroku-buildpack-grails.git",
"https://github.com/heroku/heroku-buildpack-php.git",
//Community buildpacks
"https://github.com/ddollar/heroku-buildpack-multi.git",
"https://github.com/kr/heroku-buildpack-go.git",
"https://github.com/jruby/heroku-buildpack-jruby.git",
"https://github.com/archaelus/heroku-buildpack-erlang.git",
"https://github.com/atris/heroku-buildpack-C.git",
"https://github.com/miyagawa/heroku-buildpack-perl.git",
"https://github.com/igrigorik/heroku-buildpack-dart.git",
"https://github.com/ericfode/heroku-buildpack-rust.git",
"https://github.com/oortcloud/heroku-buildpack-meteorite.git",
} |
As you mentioned, at this point I think it is clear the finalizer is not the culprit. |
It looks like we don't really handle using SSL from multiple threads too well, so that explains why using |
This should be fixed with libgit2/libgit2#2421, could you try it out? |
I checked out your branch with the fix into the vendor folder, and re-installed libgit2. But, I still get the same errors: https://gist.github.com/c4milo/cd4d67ae5985a83ebc5d |
Make sure you remove the old version from |
If that doesn't fix it, could you attach |
Removed git2go.a and I still get the errors. Regarding attaching GDB, I'm using OSX Mavericks and currently running into this issue: http://stackoverflow.com/questions/19745549/golang-cannot-get-gdb-working-for-go-programs-using-c-libraries |
|
Oh nice. Yeah, I was able to use |
Turns out our handling of openssl with threading is completely broken, I'm working on fixing it properly. |
I'm glad you found the problem. 👯 Looking forward to your patch. |
Alright, now it's fixed for real, can you test with the current version of |
It seems to happen less often but I'm still getting errors. |
OpenSSL seems to be very picky about where it gets initialised and isn't explicit about it. In the branch I've moved to init it during the general library init, which is not great, but seems to be required. Could you take another look? I used to be able to reproduce with the last few commits by setting a high |
@carlosmn I'm not sure I understand what you are asking me to do. |
ah sorry, I get it now. I'm going to test again and let you know my findings. |
So far, I haven't been able to reproduce it again. I think that did it @carlosmn. It seems to be a bit slower than before but it could also be due to other factors. Nice work. |
There is a |
Makes sense. Thank you for explaining :) |
libgit2 was fixed a while ago, and we're using a fixed version in |
I'm still getting familiar with git2go and libgit2, but I did some digging and it seems
git_clone()
already does deallocategit_repository
: https://github.com/libgit2/libgit2/blob/development/src/clone.c#L425. So, having this finalizer seems unnecessary: https://github.com/libgit2/git2go/blob/make-static/clone.go#L53The text was updated successfully, but these errors were encountered: