From db06574188ed9d2b9c24cd2a0d699ec8715f123b Mon Sep 17 00:00:00 2001 From: Paul Hinze Date: Mon, 21 Mar 2016 18:17:18 -0500 Subject: [PATCH] terraform: share graph walker's variables lock w/ interpolater The graph walker holds a lock that's passed down to BuiltinEvalContext and guards access to interpolation variables as they're written using SetVariables. The likely problem being expressed in #5733 is that the same map reference is also passed down to the Interpolater.Variables field, which is used for variable lookup. Here, we plumb the same lock we're using to guard access for writes down and acquire it before doing variable reads as well. It's not as fine grained as perhaps it could be, but all the context tests pass and I believe this should address #5733. --- terraform/graph_walk_context.go | 11 ++++++----- terraform/interpolate.go | 13 ++++++++----- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/terraform/graph_walk_context.go b/terraform/graph_walk_context.go index 2994081ffb5b..ac6310d08691 100644 --- a/terraform/graph_walk_context.go +++ b/terraform/graph_walk_context.go @@ -81,11 +81,12 @@ func (w *ContextGraphWalker) EnterPath(path []string) EvalContext { StateValue: w.Context.state, StateLock: &w.Context.stateLock, Interpolater: &Interpolater{ - Operation: w.Operation, - Module: w.Context.module, - State: w.Context.state, - StateLock: &w.Context.stateLock, - Variables: variables, + Operation: w.Operation, + Module: w.Context.module, + State: w.Context.state, + StateLock: &w.Context.stateLock, + Variables: variables, + VariablesLock: &w.interpolaterVarLock, }, InterpolaterVars: w.interpolaterVars, InterpolaterVarLock: &w.interpolaterVarLock, diff --git a/terraform/interpolate.go b/terraform/interpolate.go index 3db060b0b20f..7ec549c93b63 100644 --- a/terraform/interpolate.go +++ b/terraform/interpolate.go @@ -23,11 +23,12 @@ const ( // Interpolater is the structure responsible for determining the values // for interpolations such as `aws_instance.foo.bar`. type Interpolater struct { - Operation walkOperation - Module *module.Tree - State *State - StateLock *sync.RWMutex - Variables map[string]string + Operation walkOperation + Module *module.Tree + State *State + StateLock *sync.RWMutex + Variables map[string]string + VariablesLock *sync.Mutex } // InterpolationScope is the current scope of execution. This is required @@ -273,6 +274,8 @@ func (i *Interpolater) valueUserVar( n string, v *config.UserVariable, result map[string]ast.Variable) error { + i.VariablesLock.Lock() + defer i.VariablesLock.Unlock() val, ok := i.Variables[v.Name] if ok { result[n] = ast.Variable{