command/build: Redo interrupt handling to be more robust

This commit is contained in:
Mitchell Hashimoto 2013-06-14 17:20:11 -07:00
parent ea01d7b2c6
commit 4c1873d1f3
2 changed files with 22 additions and 35 deletions

View File

@ -1,4 +0,0 @@
package build
type config struct {
}

View File

@ -161,12 +161,28 @@ func (c Command) Run(env packer.Environment, args []string) int {
} }
// Run all the builds in parallel and wait for them to complete // Run all the builds in parallel and wait for them to complete
var wg sync.WaitGroup var interruptWg, wg sync.WaitGroup
interrupted := false
artifacts := make(map[string]packer.Artifact) artifacts := make(map[string]packer.Artifact)
for _, b := range builds { for _, b := range builds {
// Increment the waitgroup so we wait for this item to finish properly // Increment the waitgroup so we wait for this item to finish properly
wg.Add(1) wg.Add(1)
// Handle interrupts for this build
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt)
defer signal.Stop(sigCh)
go func(b packer.Build) {
<-sigCh
interruptWg.Add(1)
defer interruptWg.Done()
interrupted = true
log.Printf("Stopping build: %s", b.Name())
b.Cancel()
log.Printf("Build cancelled: %s", b.Name())
}(b)
// Run the build in a goroutine // Run the build in a goroutine
go func(b packer.Build) { go func(b packer.Build) {
defer wg.Done() defer wg.Done()
@ -187,37 +203,13 @@ func (c Command) Run(env packer.Environment, args []string) int {
log.Printf("Debug enabled, so waiting for build to finish: %s", b.Name()) log.Printf("Debug enabled, so waiting for build to finish: %s", b.Name())
wg.Wait() wg.Wait()
} }
if interrupted {
log.Println("Interrupted, not going to start any more builds.")
break
}
} }
// Handle signals
var interruptWg sync.WaitGroup
interrupted := false
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt)
go func() {
<-sigCh
interruptWg.Add(1)
defer interruptWg.Done()
interrupted = true
log.Println("Interrupted! Cancelling builds...")
var wg sync.WaitGroup
for _, b := range builds {
wg.Add(1)
go func(b packer.Build) {
defer wg.Done()
log.Printf("Stopping build: %s", b.Name())
b.Cancel()
log.Printf("Build cancelled: %s", b.Name())
}(b)
}
wg.Wait()
}()
// Wait for both the builds to complete and the interrupt handler, // Wait for both the builds to complete and the interrupt handler,
// if it is interrupted. // if it is interrupted.
@ -226,7 +218,6 @@ func (c Command) Run(env packer.Environment, args []string) int {
log.Printf("Builds completed. Waiting on interrupt barrier...") log.Printf("Builds completed. Waiting on interrupt barrier...")
interruptWg.Wait() interruptWg.Wait()
log.Printf("Interrupt barrier passed.")
if interrupted { if interrupted {
env.Ui().Say("Cleanly cancelled builds after being interrupted.") env.Ui().Say("Cleanly cancelled builds after being interrupted.")