ast/lir: simplify concurrent use of AST, which is globally stateful

Fixes #10415
This commit is contained in:
Ry Biesemeyer 2019-02-07 18:53:13 +00:00
parent 9277917875
commit cfeaa54115

View file

@ -7,30 +7,62 @@ require "logstash/compiler/treetop_monkeypatches"
module LogStash; module Config; module AST module LogStash; module Config; module AST
PROCESS_ESCAPE_SEQUENCES = :process_escape_sequences PROCESS_ESCAPE_SEQUENCES = :process_escape_sequences
def self.deferred_conditionals=(val) class << self
# @api private
MUTEX = Mutex.new
# Executes the given block with exclusive access to the AST global variables
#
# @yieldreturn [Object]: the object that is returned from the block is returned by this method
#
# @return [Object]
def exclusive
MUTEX.synchronize { yield }
end
def deferred_conditionals=(val)
ensure_exclusive!
@deferred_conditionals = val @deferred_conditionals = val
end end
def self.deferred_conditionals def deferred_conditionals
ensure_exclusive!
@deferred_conditionals @deferred_conditionals
end end
def self.deferred_conditionals_index def deferred_conditionals_index
ensure_exclusive!
@deferred_conditionals_index @deferred_conditionals_index
end end
def self.deferred_conditionals_index=(val) def deferred_conditionals_index=(val)
ensure_exclusive!
@deferred_conditionals_index = val @deferred_conditionals_index = val
end end
def self.plugin_instance_index def plugin_instance_index
ensure_exclusive!
@plugin_instance_index @plugin_instance_index
end end
def self.plugin_instance_index=(val) def plugin_instance_index=(val)
ensure_exclusive!
@plugin_instance_index = val @plugin_instance_index = val
end end
private
# Raises a descriptive error if the thread in which it is invoked does
# not have exclusive access.
#
# @raise [RuntimeError]
def ensure_exclusive!
return if MUTEX.owned?
raise "Illegal access without exclusive lock at `#{caller[1]}`"
end
end
class Node < Treetop::Runtime::SyntaxNode class Node < Treetop::Runtime::SyntaxNode
include LogStashCompilerLSCLGrammar::LogStash::Compiler::LSCL::AST::Helpers include LogStashCompilerLSCLGrammar::LogStash::Compiler::LSCL::AST::Helpers
@ -46,6 +78,15 @@ module LogStash; module Config; module AST
def compile def compile
LogStash::Config::AST.exclusive { do_compile }
end
private
# NON-threadsafe method compiles an AST into executable Ruby code.
# @see Config#compile, which is a threadsafe wrapper around this method.
# @api private
def do_compile
LogStash::Config::AST.deferred_conditionals = [] LogStash::Config::AST.deferred_conditionals = []
LogStash::Config::AST.deferred_conditionals_index = 0 LogStash::Config::AST.deferred_conditionals_index = 0
LogStash::Config::AST.plugin_instance_index = 0 LogStash::Config::AST.plugin_instance_index = 0
@ -491,6 +532,7 @@ module LogStash; module Config; module AST
end; end; end end; end; end
# Monkeypatch Treetop::Runtime::SyntaxNode's inspect method to skip # Monkeypatch Treetop::Runtime::SyntaxNode's inspect method to skip
# any Whitespace or SyntaxNodes with no children. # any Whitespace or SyntaxNodes with no children.
class Treetop::Runtime::SyntaxNode class Treetop::Runtime::SyntaxNode