From bbde7e3e35d4cf65e4ca116522c9eef1b4e5cfff Mon Sep 17 00:00:00 2001 From: James Bardin Date: Wed, 2 Oct 2019 13:42:22 -0400 Subject: [PATCH] copy client pointer for keep-alive loop If a connection fails and attempts to reconnect after the keep-alive loop started, the client will be pulled out from under the keep-alive requests. Close over a local copy of the client, so that reconnecting doesn't race with the keepalive loop terminating. --- communicator/ssh/communicator.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/communicator/ssh/communicator.go b/communicator/ssh/communicator.go index de074064b..58ecbec9d 100644 --- a/communicator/ssh/communicator.go +++ b/communicator/ssh/communicator.go @@ -235,6 +235,10 @@ func (c *Communicator) Connect(o terraform.UIOutput) (err error) { // Start a keepalive goroutine to help maintain the connection for // long-running commands. log.Printf("[DEBUG] starting ssh KeepAlives") + + // We wont a local copy of the ssh client pointer, so that a reconnect + // doesn't race with the running keep-alive loop. + sshClient := c.client go func() { defer cancelKeepAlive() // Along with the KeepAlives generating packets to keep the tcp @@ -249,7 +253,7 @@ func (c *Communicator) Connect(o terraform.UIOutput) (err error) { for { select { case <-t.C: - _, _, err := c.client.SendRequest("keepalive@terraform.io", true, nil) + _, _, err := sshClient.SendRequest("keepalive@terraform.io", true, nil) respCh <- err case <-ctx.Done(): return