# frozen_string_literal: truemodulePumaclassCluster<Puma::Runner#—————————————————————— DO NOT USE — this class is for internal use only ———# This class is instantiated by the `Puma::Cluster` and represents a single# worker process.## At the core of this class is running an instance of `Puma::Server` which# gets created via the `start_server` method from the `Puma::Runner` class# that this inherits from.classWorker<Puma::Runner# :nodoc:attr_reader:index,:masterdefinitialize(index:,master:,launcher:,pipes:,server: nil)super(launcher)@index=index@master=master@check_pipe=pipes[:check_pipe]@worker_write=pipes[:worker_write]@fork_pipe=pipes[:fork_pipe]@wakeup=pipes[:wakeup]@server=server@hook_data={}enddefruntitle="puma: cluster worker #{index}: #{master}"title+=" [#{@options[:tag]}]"if@options[:tag]&&!@options[:tag].empty?$0=titleSignal.trap"SIGINT","IGNORE"Signal.trap"SIGCHLD","DEFAULT"Thread.newdoPuma.set_thread_name"wrkr check"@check_pipe.wait_readablelog"! Detected parent died, dying"exit!1end# If we're not running under a Bundler context, then# report the info about the context we will be usingif!ENV['BUNDLE_GEMFILE']ifFile.exist?("Gemfile")log"+ Gemfile in context: #{File.expand_path("Gemfile")}"elsifFile.exist?("gems.rb")log"+ Gemfile in context: #{File.expand_path("gems.rb")}"endend# Invoke any worker boot hooks so they can get# things in shape before booting the app.@config.run_hooks(:before_worker_boot,index,@log_writer,@hook_data)beginserver=@server||=start_serverrescueException=>elog"! Unable to start worker"logeloge.backtrace.join("\n ")exit1endrestart_server=Queue.new<<true<<falsefork_worker=@options[:fork_worker]&&index==0iffork_workerrestart_server.clearworker_pids=[]Signal.trap"SIGCHLD"dowakeup!ifworker_pids.reject!do|p|Process.wait(p,Process::WNOHANG)rescuetrueendendThread.newdoPuma.set_thread_name"wrkr fork"while(idx=@fork_pipe.gets)idx=idx.to_iifidx==-1# stop serverifrestart_server.length>0restart_server.clearserver.begin_restart(true)@config.run_hooks(:before_refork,nil,@log_writer,@hook_data)endelsifidx==-2# refork cycle is done@config.run_hooks(:after_refork,nil,@log_writer,@hook_data)elsifidx==0# restart serverrestart_server<<true<<falseelse# fork workerworker_pids<<pid=spawn_worker(idx)@worker_write<<"#{PIPE_FORK}#{pid}:#{idx}\n"rescuenilendendendendSignal.trap"SIGTERM"do@worker_write<<"#{PIPE_EXTERNAL_TERM}#{Process.pid}\n"rescuenilrestart_server.clearserver.stoprestart_server<<falseendbegin@worker_write<<"#{PIPE_BOOT}#{Process.pid}:#{index}\n"rescueSystemCallError,IOErrorPuma::Util.purge_interrupt_queueSTDERR.puts"Master seems to have exited, exiting."returnendwhilerestart_server.popserver_thread=server.runif@log_writer.debug?&&index==0debug_loaded_extensions"Loaded Extensions - worker 0:"endstat_thread||=Thread.new(@worker_write)do|io|Puma.set_thread_name"stat pld"base_payload="#{PIPE_PING}#{Process.pid}"whiletruebeginb=server.backlog||0r=server.running||0t=server.pool_capacity||0m=server.max_threads||0rc=server.requests_count||0bt=server.busy_threads||0payload=%Q!#{base_payload}{ "backlog":#{b}, "running":#{r}, "pool_capacity":#{t}, "max_threads":#{m}, "requests_count":#{rc}, "busy_threads":#{bt} }\n!io<<payloadrescueIOErrorPuma::Util.purge_interrupt_queuebreakendsleep@options[:worker_check_interval]endendserver_thread.joinend# Invoke any worker shutdown hooks so they can prevent the worker# exiting until any background operations are completed@config.run_hooks(:before_worker_shutdown,index,@log_writer,@hook_data)ensure@worker_write<<"#{PIPE_TERM}#{Process.pid}\n"rescuenil@worker_write.closeendprivatedefspawn_worker(idx)@config.run_hooks(:before_worker_fork,idx,@log_writer,@hook_data)pid=forkdonew_worker=Worker.newindex: idx,master: master,launcher: @launcher,pipes: {check_pipe: @check_pipe,worker_write: @worker_write},server: @servernew_worker.runendif!pidlog"! Complete inability to spawn new workers detected"log"! Seppuku is the only choice."exit!1end@config.run_hooks(:after_worker_fork,idx,@log_writer,@hook_data)pidendendendend