func LockWithContext(ctx context.Context, s Locker, info *LockInfo) (string, error) {
	delay := time.Second
	maxDelay := 16 * time.Second
	for {
		id, err := s.Lock(info)
		if err == nil {
			return id, nil
		}
		le, ok := err.(*LockError)
		if !ok {
			return "", err
		}
		if le == nil || le.Info == nil || le.Info.ID == "" {
			return "", err
		}
		if postLockHook != nil {
			postLockHook()
		}
		select {
		case <-ctx.Done():
			return "", err
		case <-time.After(delay):
			if delay < maxDelay {
				delay *= 2
			}
		}
	}
}
LockWithContext locks the given state manager using the provided context
for both timeout and cancellation.

This method has a built-in retry/backoff behavior up to the context's
timeout.
package statemgr
import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"math/rand"
	"os"
	"os/user"
	"strings"
	"text/template"
	"time"
	uuid "github.com/hashicorp/go-uuid"
	"github.com/hashicorp/terraform/version"
)
var rngSource = rand.New(rand.NewSource(time.Now().UnixNano()))
type Locker interface {
	Lock(info *LockInfo) (string, error)
	Unlock(id string) error
}
var postLockHook func()