builder/common: Fix nil deref on race condition [GH-52]

When verifying large files, the checksum would take a long time and
downloader would be nil. When the goroutine asked for progress,
it would raise a nil exception.
This commit is contained in:
Mitchell Hashimoto 2013-06-28 22:34:43 -04:00
parent 2bdd838d90
commit daac8b959f
2 changed files with 12 additions and 3 deletions

View File

@ -7,6 +7,7 @@ import (
"fmt"
"hash"
"io"
"log"
"net/http"
"net/url"
"os"
@ -73,6 +74,7 @@ func (d *DownloadClient) Cancel() {
func (d *DownloadClient) Get() (string, error) {
// If we already have the file and it matches, then just return the target path.
if verify, _ := d.VerifyChecksum(d.config.TargetPath); verify {
log.Println("Initial checksum matched, no download needed.")
return d.config.TargetPath, nil
}
@ -81,6 +83,8 @@ func (d *DownloadClient) Get() (string, error) {
return "", err
}
log.Printf("Parsed URL: %#v", url)
// Files when we don't copy the file are special cased.
var finalPath string
if url.Scheme == "file" && !d.config.CopyFile {
@ -101,6 +105,7 @@ func (d *DownloadClient) Get() (string, error) {
}
defer f.Close()
log.Printf("Downloading: %s", url.String())
err = d.downloader.Download(f, url)
}
@ -117,6 +122,10 @@ func (d *DownloadClient) Get() (string, error) {
// PercentProgress returns the download progress as a percentage.
func (d *DownloadClient) PercentProgress() uint {
if d.downloader == nil {
return 0
}
return uint((float64(d.downloader.Progress()) / float64(d.downloader.Total())) * 100)
}
@ -133,6 +142,7 @@ func (d *DownloadClient) VerifyChecksum(path string) (bool, error) {
}
defer f.Close()
log.Printf("Verifying checksum of %s", path)
d.config.Hash.Reset()
io.Copy(d.config.Hash, f)
return bytes.Compare(d.config.Hash.Sum(nil), d.config.Checksum) == 0, nil

View File

@ -35,9 +35,7 @@ func (s *stepDownloadISO) Run(state map[string]interface{}) multistep.StepAction
checksum, err := hex.DecodeString(config.ISOMD5)
if err != nil {
err := fmt.Errorf("Error parsing checksum: %s", err)
state["error"] = err
ui.Error(err.Error())
state["error"] = fmt.Errorf("Error parsing checksum: %s", err)
return multistep.ActionHalt
}
@ -111,6 +109,7 @@ DownloadWaitLoop:
}
defer sourceF.Close()
log.Printf("Copying ISO to temp location: %s", tempdir)
if _, err := io.Copy(f, sourceF); err != nil {
state["error"] = fmt.Errorf("Error copying ISO: %s", err)
return multistep.ActionHalt