From 26a998f7210246207337d64613f059c70b1659cb Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 8 May 2013 11:54:59 -0700 Subject: [PATCH] packer/plugin: Managed clients for automatic cleanup --- packer.go | 3 +-- packer/plugin/client.go | 30 ++++++++++++++++++++++++++++++ packer/plugin/command.go | 2 +- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/packer.go b/packer.go index 00243f182..afd6873de 100644 --- a/packer.go +++ b/packer.go @@ -8,7 +8,6 @@ import ( "log" "os" "os/exec" - "time" ) func main() { @@ -41,6 +40,6 @@ func main() { } exitCode, _ := env.Cli(os.Args[1:]) - time.Sleep(1 * time.Second) + plugin.CleanupClients() os.Exit(exitCode) } diff --git a/packer/plugin/client.go b/packer/plugin/client.go index 1c2243733..bb20ba077 100644 --- a/packer/plugin/client.go +++ b/packer/plugin/client.go @@ -8,15 +8,39 @@ import ( "log" "os/exec" "strings" + "sync" "time" ) +// This is a slice of the "managed" clients which are cleaned up when +// calling Cleanup +var managedClients = make([]*client, 0, 5) + type client struct { cmd *exec.Cmd exited bool doneLogging bool } +// This makes sure all the managed subprocesses are killed and properly +// logged. This should be called before the parent process running the +// plugins exits. +func CleanupClients() { + // Kill all the managed clients in parallel and use a WaitGroup + // to wait for them all to finish up. + var wg sync.WaitGroup + for _, client := range managedClients { + wg.Add(1) + + go func() { + client.Kill() + wg.Done() + }() + } + + wg.Wait() +} + func NewClient(cmd *exec.Cmd) *client { return &client{ cmd, @@ -25,6 +49,12 @@ func NewClient(cmd *exec.Cmd) *client { } } +func NewManagedClient(cmd *exec.Cmd) (result *client) { + result = NewClient(cmd) + managedClients = append(managedClients, result) + return +} + func (c *client) Exited() bool { return c.exited } diff --git a/packer/plugin/command.go b/packer/plugin/command.go index 55539f585..9b98c87f0 100644 --- a/packer/plugin/command.go +++ b/packer/plugin/command.go @@ -52,7 +52,7 @@ func (c *cmdCommand) checkExit(p interface{}, cb func()) { // // This function guarantees the subprocess will end in a timely manner. func Command(cmd *exec.Cmd) (result packer.Command, err error) { - cmdClient := NewClient(cmd) + cmdClient := NewManagedClient(cmd) address, err := cmdClient.Start() if err != nil { return