# This file is distributed under New Relic's license terms. # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details. # frozen_string_literal: true # The Worker class makes it easy to stop and start a thread at will. # Some basic error handling/capture is wrapped around the Thread to help # propagate the exceptions arising from the threaded processes to the main process # where the main agent code lives. module NewRelic::Agent module InfiniteTracing class Worker attr_reader :name, :error def initialize(name, &job) @name = name @job = job @error = nil @worker_thread = nil @lock = Mutex.new @lock.synchronize { start_thread } end def status return 'error' if error? @lock.synchronize do return 'stopped' if @worker_thread.nil? @worker_thread.status || 'idle' end end def error? !!@error end def join(timeout = nil) return unless @worker_thread NewRelic::Agent.logger.debug("joining worker #{@name} thread...") @worker_thread.join(timeout) end def stop @lock.synchronize do return unless @worker_thread NewRelic::Agent.logger.debug("stopping worker #{@name} thread...") @worker_thread.kill @worker_thread = nil end end private def start_thread NewRelic::Agent.logger.debug("starting worker #{@name} thread...") @worker_thread = NewRelic::Agent::Threading::AgentThread.create('infinite_tracing_worker') do catch(:exit) do begin @job.call rescue => err @error = err raise end end end @worker_thread.abort_on_exception = true if @worker_thread.respond_to?(:report_on_exception) @worker_thread.report_on_exception = NewRelic::Agent.config[:log_level] == 'debug' end end end end end