Fix threading issue with strict locals

Fixes #50774

When the server boots up, 2 threads hit the same `UnboundTemplate`
instance before it has set up `@templates`. Both threads get past the
`unless template = @templates[locals]` check because
`@templates[locals]` isn't set yet. However, with `@write_lock`, one
thread waits while the other one proceeds, setting `@templates` to a
frozen hash. The second thread then gets the write lock and tries to
modify `@templates` but it has been frozen.
This commit is contained in:
Robert Fletcher 2024-01-16 16:27:58 -08:00
parent 473fd597f6
commit 929f9fd3fe

@ -26,15 +26,15 @@ def bind_locals(locals)
# while holding the lock.
template = (@templates[normalized_locals] ||= build_template(normalized_locals))
# This may have already been assigned, but we've already de-dup'd so
# reassignment is fine.
@templates[locals.dup] = template
if template.strict_locals?
# Under strict locals, we only need one template.
# This replaces the @templates Concurrent::Map with a hash which
# returns this template for every key.
@templates = Hash.new(template).freeze
else
# This may have already been assigned, but we've already de-dup'd so
# reassignment is fine.
@templates[locals.dup] = template
end
end
end