func (h *Handlers) download(v *vagrantutil.Vagrant, box, filePath string, queue <-chan chan error) { h.log().Debug("downloading %q box...", box) var listeners []chan error done := make(chan error) go func() { err := vagrantutil.Wait(v.BoxAdd(&vagrantutil.Box{Name: box})) if err == vagrantutil.ErrBoxAlreadyExists { // Ignore the above error. err = nil } done <- err }() for { select { case l := <-queue: listeners = append(listeners, l) case err := <-done: // Remove the box from in progress. h.boxMu.Lock() delete(h.boxNames, box) delete(h.boxPaths, filePath) h.boxMu.Unlock() // Defensive channel drain: try to collect listeners // that may have registered after receiving from done // but before taking boxMu lock. listeners = append(listeners, drain(queue)...) // Notify all listeners. for _, l := range listeners { l <- err } h.log().Debug("downloading %q box finished: err=%v", box, err) return } } }