diff --git a/packer/plugin/client.go b/packer/plugin/client.go index 44ad9a08a..c8e82d559 100644 --- a/packer/plugin/client.go +++ b/packer/plugin/client.go @@ -20,6 +20,8 @@ var managedClients = make([]*client, 0, 5) type client struct { config *ClientConfig exited bool + started bool + startL sync.Mutex doneLogging bool } @@ -86,12 +88,7 @@ func NewClient(config *ClientConfig) (c *client) { config.StartTimeout = 1 * time.Minute } - c = &client{ - config, - false, - false, - } - + c = &client{config: config} if config.Managed { managedClients = append(managedClients, c) } @@ -139,8 +136,13 @@ func (c *client) Kill() { // Once a client has been started once, it cannot be started again, even if // it was killed. func (c *client) Start() (address string, err error) { - // TODO: Make only run once - // TODO: Mutex + c.startL.Lock() + defer c.startL.Unlock() + + if c.started { + panic("plugin client already started once") + } + c.started = true env := []string{ fmt.Sprintf("PACKER_PLUGIN_MIN_PORT=%d", c.config.MinPort), diff --git a/packer/plugin/client_test.go b/packer/plugin/client_test.go index 5b757c206..f8c4ec75e 100644 --- a/packer/plugin/client_test.go +++ b/packer/plugin/client_test.go @@ -33,6 +33,22 @@ func TestClient(t *testing.T) { } } +func TestClient_Start_Once(t *testing.T) { + process := helperProcess("mock") + c := NewClient(&ClientConfig{Cmd: process}) + defer c.Kill() + + defer func() { + p := recover() + if p == nil { + t.Fatal("should've paniced") + } + }() + + c.Start() + c.Start() +} + func TestClient_Start_Timeout(t *testing.T) { config := &ClientConfig{ Cmd: helperProcess("start-timeout"),