jun-puma 1.0.1-java → 1.0.2-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/puma/puma_http11.jar +0 -0
- metadata +3 -81
- data/bin/puma-wild +0 -25
- data/docs/architecture.md +0 -74
- data/docs/compile_options.md +0 -55
- data/docs/deployment.md +0 -102
- data/docs/fork_worker.md +0 -31
- data/docs/images/puma-connection-flow-no-reactor.png +0 -0
- data/docs/images/puma-connection-flow.png +0 -0
- data/docs/images/puma-general-arch.png +0 -0
- data/docs/jungle/README.md +0 -9
- data/docs/jungle/rc.d/README.md +0 -74
- data/docs/jungle/rc.d/puma +0 -61
- data/docs/jungle/rc.d/puma.conf +0 -10
- data/docs/kubernetes.md +0 -78
- data/docs/nginx.md +0 -80
- data/docs/plugins.md +0 -38
- data/docs/rails_dev_mode.md +0 -28
- data/docs/restart.md +0 -64
- data/docs/signals.md +0 -98
- data/docs/stats.md +0 -142
- data/docs/systemd.md +0 -244
- data/docs/testing_benchmarks_local_files.md +0 -150
- data/docs/testing_test_rackup_ci_files.md +0 -36
- data/ext/puma_http11/PumaHttp11Service.java +0 -17
- data/ext/puma_http11/ext_help.h +0 -15
- data/ext/puma_http11/http11_parser.c +0 -1057
- data/ext/puma_http11/http11_parser.h +0 -65
- data/ext/puma_http11/http11_parser.java.rl +0 -145
- data/ext/puma_http11/http11_parser.rl +0 -149
- data/ext/puma_http11/http11_parser_common.rl +0 -54
- data/ext/puma_http11/mini_ssl.c +0 -832
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +0 -15
- data/ext/puma_http11/org/jruby/puma/Http11.java +0 -226
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +0 -455
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +0 -508
- data/ext/puma_http11/puma_http11.c +0 -492
- data/lib/puma/app/status.rb +0 -96
- data/lib/puma/binder.rb +0 -501
- data/lib/puma/cli.rb +0 -243
- data/lib/puma/client.rb +0 -632
- data/lib/puma/cluster/worker.rb +0 -182
- data/lib/puma/cluster/worker_handle.rb +0 -97
- data/lib/puma/cluster.rb +0 -562
- data/lib/puma/commonlogger.rb +0 -115
- data/lib/puma/configuration.rb +0 -391
- data/lib/puma/const.rb +0 -289
- data/lib/puma/control_cli.rb +0 -316
- data/lib/puma/detect.rb +0 -45
- data/lib/puma/dsl.rb +0 -1204
- data/lib/puma/error_logger.rb +0 -113
- data/lib/puma/events.rb +0 -57
- data/lib/puma/io_buffer.rb +0 -46
- data/lib/puma/jruby_restart.rb +0 -27
- data/lib/puma/json_serialization.rb +0 -96
- data/lib/puma/launcher/bundle_pruner.rb +0 -104
- data/lib/puma/launcher.rb +0 -484
- data/lib/puma/log_writer.rb +0 -147
- data/lib/puma/minissl/context_builder.rb +0 -95
- data/lib/puma/minissl.rb +0 -458
- data/lib/puma/null_io.rb +0 -61
- data/lib/puma/plugin/systemd.rb +0 -90
- data/lib/puma/plugin/tmp_restart.rb +0 -36
- data/lib/puma/plugin.rb +0 -111
- data/lib/puma/rack/builder.rb +0 -297
- data/lib/puma/rack/urlmap.rb +0 -93
- data/lib/puma/rack_default.rb +0 -24
- data/lib/puma/reactor.rb +0 -125
- data/lib/puma/request.rb +0 -671
- data/lib/puma/runner.rb +0 -213
- data/lib/puma/sd_notify.rb +0 -149
- data/lib/puma/server.rb +0 -664
- data/lib/puma/single.rb +0 -69
- data/lib/puma/state_file.rb +0 -68
- data/lib/puma/thread_pool.rb +0 -434
- data/lib/puma/util.rb +0 -141
- data/lib/puma.rb +0 -78
- data/lib/rack/handler/puma.rb +0 -141
- data/tools/Dockerfile +0 -16
- data/tools/trickletest.rb +0 -44
    
        data/lib/puma/cluster.rb
    DELETED
    
    | @@ -1,562 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            require_relative 'runner'
         | 
| 4 | 
            -
            require_relative 'util'
         | 
| 5 | 
            -
            require_relative 'plugin'
         | 
| 6 | 
            -
            require_relative 'cluster/worker_handle'
         | 
| 7 | 
            -
            require_relative 'cluster/worker'
         | 
| 8 | 
            -
             | 
| 9 | 
            -
            module Puma
         | 
| 10 | 
            -
              # This class is instantiated by the `Puma::Launcher` and used
         | 
| 11 | 
            -
              # to boot and serve a Ruby application when puma "workers" are needed
         | 
| 12 | 
            -
              # i.e. when using multi-processes. For example `$ puma -w 5`
         | 
| 13 | 
            -
              #
         | 
| 14 | 
            -
              # An instance of this class will spawn the number of processes passed in
         | 
| 15 | 
            -
              # via the `spawn_workers` method call. Each worker will have it's own
         | 
| 16 | 
            -
              # instance of a `Puma::Server`.
         | 
| 17 | 
            -
              class Cluster < Runner
         | 
| 18 | 
            -
                def initialize(launcher)
         | 
| 19 | 
            -
                  super(launcher)
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                  @phase = 0
         | 
| 22 | 
            -
                  @workers = []
         | 
| 23 | 
            -
                  @next_check = Time.now
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                  @phased_restart = false
         | 
| 26 | 
            -
                end
         | 
| 27 | 
            -
             | 
| 28 | 
            -
                # Returns the list of cluster worker handles.
         | 
| 29 | 
            -
                # @return [Array<Puma::Cluster::WorkerHandle>]
         | 
| 30 | 
            -
                attr_reader :workers
         | 
| 31 | 
            -
             | 
| 32 | 
            -
                def stop_workers
         | 
| 33 | 
            -
                  log "- Gracefully shutting down workers..."
         | 
| 34 | 
            -
                  @workers.each { |x| x.term }
         | 
| 35 | 
            -
             | 
| 36 | 
            -
                  begin
         | 
| 37 | 
            -
                    loop do
         | 
| 38 | 
            -
                      wait_workers
         | 
| 39 | 
            -
                      break if @workers.reject {|w| w.pid.nil?}.empty?
         | 
| 40 | 
            -
                      sleep 0.2
         | 
| 41 | 
            -
                    end
         | 
| 42 | 
            -
                  rescue Interrupt
         | 
| 43 | 
            -
                    log "! Cancelled waiting for workers"
         | 
| 44 | 
            -
                  end
         | 
| 45 | 
            -
                end
         | 
| 46 | 
            -
             | 
| 47 | 
            -
                def start_phased_restart
         | 
| 48 | 
            -
                  @events.fire_on_restart!
         | 
| 49 | 
            -
                  @phase += 1
         | 
| 50 | 
            -
                  log "- Starting phased worker restart, phase: #{@phase}"
         | 
| 51 | 
            -
             | 
| 52 | 
            -
                  # Be sure to change the directory again before loading
         | 
| 53 | 
            -
                  # the app. This way we can pick up new code.
         | 
| 54 | 
            -
                  dir = @launcher.restart_dir
         | 
| 55 | 
            -
                  log "+ Changing to #{dir}"
         | 
| 56 | 
            -
                  Dir.chdir dir
         | 
| 57 | 
            -
                end
         | 
| 58 | 
            -
             | 
| 59 | 
            -
                def redirect_io
         | 
| 60 | 
            -
                  super
         | 
| 61 | 
            -
             | 
| 62 | 
            -
                  @workers.each { |x| x.hup }
         | 
| 63 | 
            -
                end
         | 
| 64 | 
            -
             | 
| 65 | 
            -
                def spawn_workers
         | 
| 66 | 
            -
                  diff = @options[:workers] - @workers.size
         | 
| 67 | 
            -
                  return if diff < 1
         | 
| 68 | 
            -
             | 
| 69 | 
            -
                  master = Process.pid
         | 
| 70 | 
            -
                  if @options[:fork_worker]
         | 
| 71 | 
            -
                    @fork_writer << "-1\n"
         | 
| 72 | 
            -
                  end
         | 
| 73 | 
            -
             | 
| 74 | 
            -
                  diff.times do
         | 
| 75 | 
            -
                    idx = next_worker_index
         | 
| 76 | 
            -
             | 
| 77 | 
            -
                    if @options[:fork_worker] && idx != 0
         | 
| 78 | 
            -
                      @fork_writer << "#{idx}\n"
         | 
| 79 | 
            -
                      pid = nil
         | 
| 80 | 
            -
                    else
         | 
| 81 | 
            -
                      pid = spawn_worker(idx, master)
         | 
| 82 | 
            -
                    end
         | 
| 83 | 
            -
             | 
| 84 | 
            -
                    debug "Spawned worker: #{pid}"
         | 
| 85 | 
            -
                    @workers << WorkerHandle.new(idx, pid, @phase, @options)
         | 
| 86 | 
            -
                  end
         | 
| 87 | 
            -
             | 
| 88 | 
            -
                  if @options[:fork_worker] && all_workers_in_phase?
         | 
| 89 | 
            -
                    @fork_writer << "0\n"
         | 
| 90 | 
            -
                  end
         | 
| 91 | 
            -
                end
         | 
| 92 | 
            -
             | 
| 93 | 
            -
                # @version 5.0.0
         | 
| 94 | 
            -
                def spawn_worker(idx, master)
         | 
| 95 | 
            -
                  @config.run_hooks(:before_worker_fork, idx, @log_writer)
         | 
| 96 | 
            -
             | 
| 97 | 
            -
                  pid = fork { worker(idx, master) }
         | 
| 98 | 
            -
                  if !pid
         | 
| 99 | 
            -
                    log "! Complete inability to spawn new workers detected"
         | 
| 100 | 
            -
                    log "! Seppuku is the only choice."
         | 
| 101 | 
            -
                    exit! 1
         | 
| 102 | 
            -
                  end
         | 
| 103 | 
            -
             | 
| 104 | 
            -
                  @config.run_hooks(:after_worker_fork, idx, @log_writer)
         | 
| 105 | 
            -
                  pid
         | 
| 106 | 
            -
                end
         | 
| 107 | 
            -
             | 
| 108 | 
            -
                def cull_workers
         | 
| 109 | 
            -
                  diff = @workers.size - @options[:workers]
         | 
| 110 | 
            -
                  return if diff < 1
         | 
| 111 | 
            -
                  debug "Culling #{diff} workers"
         | 
| 112 | 
            -
             | 
| 113 | 
            -
                  workers = workers_to_cull(diff)
         | 
| 114 | 
            -
                  debug "Workers to cull: #{workers.inspect}"
         | 
| 115 | 
            -
             | 
| 116 | 
            -
                  workers.each do |worker|
         | 
| 117 | 
            -
                    log "- Worker #{worker.index} (PID: #{worker.pid}) terminating"
         | 
| 118 | 
            -
                    worker.term
         | 
| 119 | 
            -
                  end
         | 
| 120 | 
            -
                end
         | 
| 121 | 
            -
             | 
| 122 | 
            -
                def workers_to_cull(diff)
         | 
| 123 | 
            -
                  workers = @workers.sort_by(&:started_at)
         | 
| 124 | 
            -
             | 
| 125 | 
            -
                  # In fork_worker mode, worker 0 acts as our master process.
         | 
| 126 | 
            -
                  # We should avoid culling it to preserve copy-on-write memory gains.
         | 
| 127 | 
            -
                  workers.reject! { |w| w.index == 0 } if @options[:fork_worker]
         | 
| 128 | 
            -
             | 
| 129 | 
            -
                  workers[cull_start_index(diff), diff]
         | 
| 130 | 
            -
                end
         | 
| 131 | 
            -
             | 
| 132 | 
            -
                def cull_start_index(diff)
         | 
| 133 | 
            -
                  case @options[:worker_culling_strategy]
         | 
| 134 | 
            -
                  when :oldest
         | 
| 135 | 
            -
                    0
         | 
| 136 | 
            -
                  else # :youngest
         | 
| 137 | 
            -
                    -diff
         | 
| 138 | 
            -
                  end
         | 
| 139 | 
            -
                end
         | 
| 140 | 
            -
             | 
| 141 | 
            -
                # @!attribute [r] next_worker_index
         | 
| 142 | 
            -
                def next_worker_index
         | 
| 143 | 
            -
                  occupied_positions = @workers.map(&:index)
         | 
| 144 | 
            -
                  idx = 0
         | 
| 145 | 
            -
                  idx += 1 until !occupied_positions.include?(idx)
         | 
| 146 | 
            -
                  idx
         | 
| 147 | 
            -
                end
         | 
| 148 | 
            -
             | 
| 149 | 
            -
                def worker_at(idx)
         | 
| 150 | 
            -
                  @workers.find { |w| w.index == idx }
         | 
| 151 | 
            -
                end
         | 
| 152 | 
            -
             | 
| 153 | 
            -
                def all_workers_booted?
         | 
| 154 | 
            -
                  @workers.count { |w| !w.booted? } == 0
         | 
| 155 | 
            -
                end
         | 
| 156 | 
            -
             | 
| 157 | 
            -
                def all_workers_in_phase?
         | 
| 158 | 
            -
                  @workers.all? { |w| w.phase == @phase }
         | 
| 159 | 
            -
                end
         | 
| 160 | 
            -
             | 
| 161 | 
            -
                def check_workers
         | 
| 162 | 
            -
                  return if @next_check >= Time.now
         | 
| 163 | 
            -
             | 
| 164 | 
            -
                  @next_check = Time.now + @options[:worker_check_interval]
         | 
| 165 | 
            -
             | 
| 166 | 
            -
                  timeout_workers
         | 
| 167 | 
            -
                  wait_workers
         | 
| 168 | 
            -
                  cull_workers
         | 
| 169 | 
            -
                  spawn_workers
         | 
| 170 | 
            -
             | 
| 171 | 
            -
                  if all_workers_booted?
         | 
| 172 | 
            -
                    # If we're running at proper capacity, check to see if
         | 
| 173 | 
            -
                    # we need to phase any workers out (which will restart
         | 
| 174 | 
            -
                    # in the right phase).
         | 
| 175 | 
            -
                    #
         | 
| 176 | 
            -
                    w = @workers.find { |x| x.phase != @phase }
         | 
| 177 | 
            -
             | 
| 178 | 
            -
                    if w
         | 
| 179 | 
            -
                      log "- Stopping #{w.pid} for phased upgrade..."
         | 
| 180 | 
            -
                      unless w.term?
         | 
| 181 | 
            -
                        w.term
         | 
| 182 | 
            -
                        log "- #{w.signal} sent to #{w.pid}..."
         | 
| 183 | 
            -
                      end
         | 
| 184 | 
            -
                    end
         | 
| 185 | 
            -
                  end
         | 
| 186 | 
            -
             | 
| 187 | 
            -
                  t = @workers.reject(&:term?)
         | 
| 188 | 
            -
                  t.map!(&:ping_timeout)
         | 
| 189 | 
            -
             | 
| 190 | 
            -
                  @next_check = [t.min, @next_check].compact.min
         | 
| 191 | 
            -
                end
         | 
| 192 | 
            -
             | 
| 193 | 
            -
                def worker(index, master)
         | 
| 194 | 
            -
                  @workers = []
         | 
| 195 | 
            -
             | 
| 196 | 
            -
                  @master_read.close
         | 
| 197 | 
            -
                  @suicide_pipe.close
         | 
| 198 | 
            -
                  @fork_writer.close
         | 
| 199 | 
            -
             | 
| 200 | 
            -
                  pipes = { check_pipe: @check_pipe, worker_write: @worker_write }
         | 
| 201 | 
            -
                  if @options[:fork_worker]
         | 
| 202 | 
            -
                    pipes[:fork_pipe] = @fork_pipe
         | 
| 203 | 
            -
                    pipes[:wakeup] = @wakeup
         | 
| 204 | 
            -
                  end
         | 
| 205 | 
            -
             | 
| 206 | 
            -
                  server = start_server if preload?
         | 
| 207 | 
            -
                  new_worker = Worker.new index: index,
         | 
| 208 | 
            -
                                          master: master,
         | 
| 209 | 
            -
                                          launcher: @launcher,
         | 
| 210 | 
            -
                                          pipes: pipes,
         | 
| 211 | 
            -
                                          server: server
         | 
| 212 | 
            -
                  new_worker.run
         | 
| 213 | 
            -
                end
         | 
| 214 | 
            -
             | 
| 215 | 
            -
                def restart
         | 
| 216 | 
            -
                  @restart = true
         | 
| 217 | 
            -
                  stop
         | 
| 218 | 
            -
                end
         | 
| 219 | 
            -
             | 
| 220 | 
            -
                def phased_restart(refork = false)
         | 
| 221 | 
            -
                  return false if @options[:preload_app] && !refork
         | 
| 222 | 
            -
             | 
| 223 | 
            -
                  @phased_restart = true
         | 
| 224 | 
            -
                  wakeup!
         | 
| 225 | 
            -
             | 
| 226 | 
            -
                  true
         | 
| 227 | 
            -
                end
         | 
| 228 | 
            -
             | 
| 229 | 
            -
                def stop
         | 
| 230 | 
            -
                  @status = :stop
         | 
| 231 | 
            -
                  wakeup!
         | 
| 232 | 
            -
                end
         | 
| 233 | 
            -
             | 
| 234 | 
            -
                def stop_blocked
         | 
| 235 | 
            -
                  @status = :stop if @status == :run
         | 
| 236 | 
            -
                  wakeup!
         | 
| 237 | 
            -
                  @control&.stop true
         | 
| 238 | 
            -
                  Process.waitall
         | 
| 239 | 
            -
                end
         | 
| 240 | 
            -
             | 
| 241 | 
            -
                def halt
         | 
| 242 | 
            -
                  @status = :halt
         | 
| 243 | 
            -
                  wakeup!
         | 
| 244 | 
            -
                end
         | 
| 245 | 
            -
             | 
| 246 | 
            -
                def reload_worker_directory
         | 
| 247 | 
            -
                  dir = @launcher.restart_dir
         | 
| 248 | 
            -
                  log "+ Changing to #{dir}"
         | 
| 249 | 
            -
                  Dir.chdir dir
         | 
| 250 | 
            -
                end
         | 
| 251 | 
            -
             | 
| 252 | 
            -
                # Inside of a child process, this will return all zeroes, as @workers is only populated in
         | 
| 253 | 
            -
                # the master process.
         | 
| 254 | 
            -
                # @!attribute [r] stats
         | 
| 255 | 
            -
                def stats
         | 
| 256 | 
            -
                  old_worker_count = @workers.count { |w| w.phase != @phase }
         | 
| 257 | 
            -
                  worker_status = @workers.map do |w|
         | 
| 258 | 
            -
                    {
         | 
| 259 | 
            -
                      started_at: utc_iso8601(w.started_at),
         | 
| 260 | 
            -
                      pid: w.pid,
         | 
| 261 | 
            -
                      index: w.index,
         | 
| 262 | 
            -
                      phase: w.phase,
         | 
| 263 | 
            -
                      booted: w.booted?,
         | 
| 264 | 
            -
                      last_checkin: utc_iso8601(w.last_checkin),
         | 
| 265 | 
            -
                      last_status: w.last_status,
         | 
| 266 | 
            -
                    }
         | 
| 267 | 
            -
                  end
         | 
| 268 | 
            -
             | 
| 269 | 
            -
                  {
         | 
| 270 | 
            -
                    started_at: utc_iso8601(@started_at),
         | 
| 271 | 
            -
                    workers: @workers.size,
         | 
| 272 | 
            -
                    phase: @phase,
         | 
| 273 | 
            -
                    booted_workers: worker_status.count { |w| w[:booted] },
         | 
| 274 | 
            -
                    old_workers: old_worker_count,
         | 
| 275 | 
            -
                    worker_status: worker_status,
         | 
| 276 | 
            -
                  }.merge(super)
         | 
| 277 | 
            -
                end
         | 
| 278 | 
            -
             | 
| 279 | 
            -
                def preload?
         | 
| 280 | 
            -
                  @options[:preload_app]
         | 
| 281 | 
            -
                end
         | 
| 282 | 
            -
             | 
| 283 | 
            -
                # @version 5.0.0
         | 
| 284 | 
            -
                def fork_worker!
         | 
| 285 | 
            -
                  if (worker = worker_at 0)
         | 
| 286 | 
            -
                    worker.phase += 1
         | 
| 287 | 
            -
                  end
         | 
| 288 | 
            -
                  phased_restart(true)
         | 
| 289 | 
            -
                end
         | 
| 290 | 
            -
             | 
| 291 | 
            -
                # We do this in a separate method to keep the lambda scope
         | 
| 292 | 
            -
                # of the signals handlers as small as possible.
         | 
| 293 | 
            -
                def setup_signals
         | 
| 294 | 
            -
                  if @options[:fork_worker]
         | 
| 295 | 
            -
                    Signal.trap "SIGURG" do
         | 
| 296 | 
            -
                      fork_worker!
         | 
| 297 | 
            -
                    end
         | 
| 298 | 
            -
             | 
| 299 | 
            -
                    # Auto-fork after the specified number of requests.
         | 
| 300 | 
            -
                    if (fork_requests = @options[:fork_worker].to_i) > 0
         | 
| 301 | 
            -
                      @events.register(:ping!) do |w|
         | 
| 302 | 
            -
                        fork_worker! if w.index == 0 &&
         | 
| 303 | 
            -
                          w.phase == 0 &&
         | 
| 304 | 
            -
                          w.last_status[:requests_count] >= fork_requests
         | 
| 305 | 
            -
                      end
         | 
| 306 | 
            -
                    end
         | 
| 307 | 
            -
                  end
         | 
| 308 | 
            -
             | 
| 309 | 
            -
                  Signal.trap "SIGCHLD" do
         | 
| 310 | 
            -
                    wakeup!
         | 
| 311 | 
            -
                  end
         | 
| 312 | 
            -
             | 
| 313 | 
            -
                  Signal.trap "TTIN" do
         | 
| 314 | 
            -
                    @options[:workers] += 1
         | 
| 315 | 
            -
                    wakeup!
         | 
| 316 | 
            -
                  end
         | 
| 317 | 
            -
             | 
| 318 | 
            -
                  Signal.trap "TTOU" do
         | 
| 319 | 
            -
                    @options[:workers] -= 1 if @options[:workers] >= 2
         | 
| 320 | 
            -
                    wakeup!
         | 
| 321 | 
            -
                  end
         | 
| 322 | 
            -
             | 
| 323 | 
            -
                  master_pid = Process.pid
         | 
| 324 | 
            -
             | 
| 325 | 
            -
                  Signal.trap "SIGTERM" do
         | 
| 326 | 
            -
                    # The worker installs their own SIGTERM when booted.
         | 
| 327 | 
            -
                    # Until then, this is run by the worker and the worker
         | 
| 328 | 
            -
                    # should just exit if they get it.
         | 
| 329 | 
            -
                    if Process.pid != master_pid
         | 
| 330 | 
            -
                      log "Early termination of worker"
         | 
| 331 | 
            -
                      exit! 0
         | 
| 332 | 
            -
                    else
         | 
| 333 | 
            -
                      @launcher.close_binder_listeners
         | 
| 334 | 
            -
             | 
| 335 | 
            -
                      stop_workers
         | 
| 336 | 
            -
                      stop
         | 
| 337 | 
            -
                      @events.fire_on_stopped!
         | 
| 338 | 
            -
                      raise(SignalException, "SIGTERM") if @options[:raise_exception_on_sigterm]
         | 
| 339 | 
            -
                      exit 0 # Clean exit, workers were stopped
         | 
| 340 | 
            -
                    end
         | 
| 341 | 
            -
                  end
         | 
| 342 | 
            -
                end
         | 
| 343 | 
            -
             | 
| 344 | 
            -
                def run
         | 
| 345 | 
            -
                  @status = :run
         | 
| 346 | 
            -
             | 
| 347 | 
            -
                  output_header "cluster"
         | 
| 348 | 
            -
             | 
| 349 | 
            -
                  # This is aligned with the output from Runner, see Runner#output_header
         | 
| 350 | 
            -
                  log "*      Workers: #{@options[:workers]}"
         | 
| 351 | 
            -
             | 
| 352 | 
            -
                  if preload?
         | 
| 353 | 
            -
                    # Threads explicitly marked as fork safe will be ignored. Used in Rails,
         | 
| 354 | 
            -
                    # but may be used by anyone. Note that we need to explicit
         | 
| 355 | 
            -
                    # Process::Waiter check here because there's a bug in Ruby 2.6 and below
         | 
| 356 | 
            -
                    # where calling thread_variable_get on a Process::Waiter will segfault.
         | 
| 357 | 
            -
                    # We can drop that clause once those versions of Ruby are no longer
         | 
| 358 | 
            -
                    # supported.
         | 
| 359 | 
            -
                    fork_safe = ->(t) { !t.is_a?(Process::Waiter) && t.thread_variable_get(:fork_safe) }
         | 
| 360 | 
            -
             | 
| 361 | 
            -
                    before = Thread.list.reject(&fork_safe)
         | 
| 362 | 
            -
             | 
| 363 | 
            -
                    log "*     Restarts: (\u2714) hot (\u2716) phased"
         | 
| 364 | 
            -
                    log "* Preloading application"
         | 
| 365 | 
            -
                    load_and_bind
         | 
| 366 | 
            -
             | 
| 367 | 
            -
                    after = Thread.list.reject(&fork_safe)
         | 
| 368 | 
            -
             | 
| 369 | 
            -
                    if after.size > before.size
         | 
| 370 | 
            -
                      threads = (after - before)
         | 
| 371 | 
            -
                      if threads.first.respond_to? :backtrace
         | 
| 372 | 
            -
                        log "! WARNING: Detected #{after.size-before.size} Thread(s) started in app boot:"
         | 
| 373 | 
            -
                        threads.each do |t|
         | 
| 374 | 
            -
                          log "! #{t.inspect} - #{t.backtrace ? t.backtrace.first : ''}"
         | 
| 375 | 
            -
                        end
         | 
| 376 | 
            -
                      else
         | 
| 377 | 
            -
                        log "! WARNING: Detected #{after.size-before.size} Thread(s) started in app boot"
         | 
| 378 | 
            -
                      end
         | 
| 379 | 
            -
                    end
         | 
| 380 | 
            -
                  else
         | 
| 381 | 
            -
                    log "*     Restarts: (\u2714) hot (\u2714) phased"
         | 
| 382 | 
            -
             | 
| 383 | 
            -
                    unless @config.app_configured?
         | 
| 384 | 
            -
                      error "No application configured, nothing to run"
         | 
| 385 | 
            -
                      exit 1
         | 
| 386 | 
            -
                    end
         | 
| 387 | 
            -
             | 
| 388 | 
            -
                    @launcher.binder.parse @options[:binds]
         | 
| 389 | 
            -
                  end
         | 
| 390 | 
            -
             | 
| 391 | 
            -
                  read, @wakeup = Puma::Util.pipe
         | 
| 392 | 
            -
             | 
| 393 | 
            -
                  setup_signals
         | 
| 394 | 
            -
             | 
| 395 | 
            -
                  # Used by the workers to detect if the master process dies.
         | 
| 396 | 
            -
                  # If select says that @check_pipe is ready, it's because the
         | 
| 397 | 
            -
                  # master has exited and @suicide_pipe has been automatically
         | 
| 398 | 
            -
                  # closed.
         | 
| 399 | 
            -
                  #
         | 
| 400 | 
            -
                  @check_pipe, @suicide_pipe = Puma::Util.pipe
         | 
| 401 | 
            -
             | 
| 402 | 
            -
                  # Separate pipe used by worker 0 to receive commands to
         | 
| 403 | 
            -
                  # fork new worker processes.
         | 
| 404 | 
            -
                  @fork_pipe, @fork_writer = Puma::Util.pipe
         | 
| 405 | 
            -
             | 
| 406 | 
            -
                  log "Use Ctrl-C to stop"
         | 
| 407 | 
            -
             | 
| 408 | 
            -
                  single_worker_warning
         | 
| 409 | 
            -
             | 
| 410 | 
            -
                  redirect_io
         | 
| 411 | 
            -
             | 
| 412 | 
            -
                  Plugins.fire_background
         | 
| 413 | 
            -
             | 
| 414 | 
            -
                  @launcher.write_state
         | 
| 415 | 
            -
             | 
| 416 | 
            -
                  start_control
         | 
| 417 | 
            -
             | 
| 418 | 
            -
                  @master_read, @worker_write = read, @wakeup
         | 
| 419 | 
            -
             | 
| 420 | 
            -
                  @config.run_hooks(:before_fork, nil, @log_writer)
         | 
| 421 | 
            -
             | 
| 422 | 
            -
                  spawn_workers
         | 
| 423 | 
            -
             | 
| 424 | 
            -
                  Signal.trap "SIGINT" do
         | 
| 425 | 
            -
                    stop
         | 
| 426 | 
            -
                  end
         | 
| 427 | 
            -
             | 
| 428 | 
            -
                  begin
         | 
| 429 | 
            -
                    booted = false
         | 
| 430 | 
            -
                    in_phased_restart = false
         | 
| 431 | 
            -
                    workers_not_booted = @options[:workers]
         | 
| 432 | 
            -
             | 
| 433 | 
            -
                    while @status == :run
         | 
| 434 | 
            -
                      begin
         | 
| 435 | 
            -
                        if @phased_restart
         | 
| 436 | 
            -
                          start_phased_restart
         | 
| 437 | 
            -
                          @phased_restart = false
         | 
| 438 | 
            -
                          in_phased_restart = true
         | 
| 439 | 
            -
                          workers_not_booted = @options[:workers]
         | 
| 440 | 
            -
                        end
         | 
| 441 | 
            -
             | 
| 442 | 
            -
                        check_workers
         | 
| 443 | 
            -
             | 
| 444 | 
            -
                        if read.wait_readable([0, @next_check - Time.now].max)
         | 
| 445 | 
            -
                          req = read.read_nonblock(1)
         | 
| 446 | 
            -
             | 
| 447 | 
            -
                          @next_check = Time.now if req == "!"
         | 
| 448 | 
            -
                          next if !req || req == "!"
         | 
| 449 | 
            -
             | 
| 450 | 
            -
                          result = read.gets
         | 
| 451 | 
            -
                          pid = result.to_i
         | 
| 452 | 
            -
             | 
| 453 | 
            -
                          if req == "b" || req == "f"
         | 
| 454 | 
            -
                            pid, idx = result.split(':').map(&:to_i)
         | 
| 455 | 
            -
                            w = worker_at idx
         | 
| 456 | 
            -
                            w.pid = pid if w.pid.nil?
         | 
| 457 | 
            -
                          end
         | 
| 458 | 
            -
             | 
| 459 | 
            -
                          if w = @workers.find { |x| x.pid == pid }
         | 
| 460 | 
            -
                            case req
         | 
| 461 | 
            -
                            when "b"
         | 
| 462 | 
            -
                              w.boot!
         | 
| 463 | 
            -
                              log "- Worker #{w.index} (PID: #{pid}) booted in #{w.uptime.round(2)}s, phase: #{w.phase}"
         | 
| 464 | 
            -
                              @next_check = Time.now
         | 
| 465 | 
            -
                              workers_not_booted -= 1
         | 
| 466 | 
            -
                            when "e"
         | 
| 467 | 
            -
                              # external term, see worker method, Signal.trap "SIGTERM"
         | 
| 468 | 
            -
                              w.term!
         | 
| 469 | 
            -
                            when "t"
         | 
| 470 | 
            -
                              w.term unless w.term?
         | 
| 471 | 
            -
                            when "p"
         | 
| 472 | 
            -
                              status = result.sub(/^\d+/,'').chomp
         | 
| 473 | 
            -
                              w.ping!(status)
         | 
| 474 | 
            -
                              @events.fire(:ping!, w)
         | 
| 475 | 
            -
             | 
| 476 | 
            -
                              if in_phased_restart && workers_not_booted.positive? && w0 = worker_at(0)
         | 
| 477 | 
            -
                                w0.ping!(status)
         | 
| 478 | 
            -
                                @events.fire(:ping!, w0)
         | 
| 479 | 
            -
                              end
         | 
| 480 | 
            -
             | 
| 481 | 
            -
                              if !booted && @workers.none? {|worker| worker.last_status.empty?}
         | 
| 482 | 
            -
                                @events.fire_on_booted!
         | 
| 483 | 
            -
                                debug_loaded_extensions("Loaded Extensions - master:") if @log_writer.debug?
         | 
| 484 | 
            -
                                booted = true
         | 
| 485 | 
            -
                              end
         | 
| 486 | 
            -
                            end
         | 
| 487 | 
            -
                          else
         | 
| 488 | 
            -
                            log "! Out-of-sync worker list, no #{pid} worker"
         | 
| 489 | 
            -
                          end
         | 
| 490 | 
            -
                        end
         | 
| 491 | 
            -
                        if in_phased_restart && workers_not_booted.zero?
         | 
| 492 | 
            -
                          @events.fire_on_booted!
         | 
| 493 | 
            -
                          debug_loaded_extensions("Loaded Extensions - master:") if @log_writer.debug?
         | 
| 494 | 
            -
                          in_phased_restart = false
         | 
| 495 | 
            -
                        end
         | 
| 496 | 
            -
             | 
| 497 | 
            -
                      rescue Interrupt
         | 
| 498 | 
            -
                        @status = :stop
         | 
| 499 | 
            -
                      end
         | 
| 500 | 
            -
                    end
         | 
| 501 | 
            -
             | 
| 502 | 
            -
                    stop_workers unless @status == :halt
         | 
| 503 | 
            -
                  ensure
         | 
| 504 | 
            -
                    @check_pipe.close
         | 
| 505 | 
            -
                    @suicide_pipe.close
         | 
| 506 | 
            -
                    read.close
         | 
| 507 | 
            -
                    @wakeup.close
         | 
| 508 | 
            -
                  end
         | 
| 509 | 
            -
                end
         | 
| 510 | 
            -
             | 
| 511 | 
            -
                private
         | 
| 512 | 
            -
             | 
| 513 | 
            -
                def single_worker_warning
         | 
| 514 | 
            -
                  return if @options[:workers] != 1 || @options[:silence_single_worker_warning]
         | 
| 515 | 
            -
             | 
| 516 | 
            -
                  log "! WARNING: Detected running cluster mode with 1 worker."
         | 
| 517 | 
            -
                  log "! Running Puma in cluster mode with a single worker is often a misconfiguration."
         | 
| 518 | 
            -
                  log "! Consider running Puma in single-mode (workers = 0) in order to reduce memory overhead."
         | 
| 519 | 
            -
                  log "! Set the `silence_single_worker_warning` option to silence this warning message."
         | 
| 520 | 
            -
                end
         | 
| 521 | 
            -
             | 
| 522 | 
            -
                # loops thru @workers, removing workers that exited, and calling
         | 
| 523 | 
            -
                # `#term` if needed
         | 
| 524 | 
            -
                def wait_workers
         | 
| 525 | 
            -
                  @workers.reject! do |w|
         | 
| 526 | 
            -
                    next false if w.pid.nil?
         | 
| 527 | 
            -
                    begin
         | 
| 528 | 
            -
                      if Process.wait(w.pid, Process::WNOHANG)
         | 
| 529 | 
            -
                        true
         | 
| 530 | 
            -
                      else
         | 
| 531 | 
            -
                        w.term if w.term?
         | 
| 532 | 
            -
                        nil
         | 
| 533 | 
            -
                      end
         | 
| 534 | 
            -
                    rescue Errno::ECHILD
         | 
| 535 | 
            -
                      begin
         | 
| 536 | 
            -
                        Process.kill(0, w.pid)
         | 
| 537 | 
            -
                        # child still alive but has another parent (e.g., using fork_worker)
         | 
| 538 | 
            -
                        w.term if w.term?
         | 
| 539 | 
            -
                        false
         | 
| 540 | 
            -
                      rescue Errno::ESRCH, Errno::EPERM
         | 
| 541 | 
            -
                        true # child is already terminated
         | 
| 542 | 
            -
                      end
         | 
| 543 | 
            -
                    end
         | 
| 544 | 
            -
                  end
         | 
| 545 | 
            -
                end
         | 
| 546 | 
            -
             | 
| 547 | 
            -
                # @version 5.0.0
         | 
| 548 | 
            -
                def timeout_workers
         | 
| 549 | 
            -
                  @workers.each do |w|
         | 
| 550 | 
            -
                    if !w.term? && w.ping_timeout <= Time.now
         | 
| 551 | 
            -
                      details = if w.booted?
         | 
| 552 | 
            -
                                  "(Worker #{w.index} failed to check in within #{@options[:worker_timeout]} seconds)"
         | 
| 553 | 
            -
                                else
         | 
| 554 | 
            -
                                  "(Worker #{w.index} failed to boot within #{@options[:worker_boot_timeout]} seconds)"
         | 
| 555 | 
            -
                                end
         | 
| 556 | 
            -
                      log "! Terminating timed out worker #{details}: #{w.pid}"
         | 
| 557 | 
            -
                      w.kill
         | 
| 558 | 
            -
                    end
         | 
| 559 | 
            -
                  end
         | 
| 560 | 
            -
                end
         | 
| 561 | 
            -
              end
         | 
| 562 | 
            -
            end
         | 
    
        data/lib/puma/commonlogger.rb
    DELETED
    
    | @@ -1,115 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module Puma
         | 
| 4 | 
            -
              # Rack::CommonLogger forwards every request to the given +app+, and
         | 
| 5 | 
            -
              # logs a line in the
         | 
| 6 | 
            -
              # {Apache common log format}[https://httpd.apache.org/docs/2.4/logs.html#common]
         | 
| 7 | 
            -
              # to the +logger+.
         | 
| 8 | 
            -
              #
         | 
| 9 | 
            -
              # If +logger+ is nil, CommonLogger will fall back +rack.errors+, which is
         | 
| 10 | 
            -
              # an instance of Rack::NullLogger.
         | 
| 11 | 
            -
              #
         | 
| 12 | 
            -
              # +logger+ can be any class, including the standard library Logger, and is
         | 
| 13 | 
            -
              # expected to have either +write+ or +<<+ method, which accepts the CommonLogger::FORMAT.
         | 
| 14 | 
            -
              # According to the SPEC, the error stream must also respond to +puts+
         | 
| 15 | 
            -
              # (which takes a single argument that responds to +to_s+), and +flush+
         | 
| 16 | 
            -
              # (which is called without arguments in order to make the error appear for
         | 
| 17 | 
            -
              # sure)
         | 
| 18 | 
            -
              class CommonLogger
         | 
| 19 | 
            -
                # Common Log Format: https://httpd.apache.org/docs/2.4/logs.html#common
         | 
| 20 | 
            -
                #
         | 
| 21 | 
            -
                #   lilith.local - - [07/Aug/2006 23:58:02 -0400] "GET / HTTP/1.1" 500 -
         | 
| 22 | 
            -
                #
         | 
| 23 | 
            -
                #   %{%s - %s [%s] "%s %s%s %s" %d %s\n} %
         | 
| 24 | 
            -
                FORMAT = %{%s - %s [%s] "%s %s%s %s" %d %s %0.4f\n}
         | 
| 25 | 
            -
             | 
| 26 | 
            -
                HIJACK_FORMAT = %{%s - %s [%s] "%s %s%s %s" HIJACKED -1 %0.4f\n}
         | 
| 27 | 
            -
             | 
| 28 | 
            -
                LOG_TIME_FORMAT = '%d/%b/%Y:%H:%M:%S %z'
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                CONTENT_LENGTH       = 'Content-Length' # should be lower case from app,
         | 
| 31 | 
            -
                                                        # Util::HeaderHash allows mixed
         | 
| 32 | 
            -
                HTTP_VERSION         = Const::HTTP_VERSION
         | 
| 33 | 
            -
                HTTP_X_FORWARDED_FOR = Const::HTTP_X_FORWARDED_FOR
         | 
| 34 | 
            -
                PATH_INFO            = Const::PATH_INFO
         | 
| 35 | 
            -
                QUERY_STRING         = Const::QUERY_STRING
         | 
| 36 | 
            -
                REMOTE_ADDR          = Const::REMOTE_ADDR
         | 
| 37 | 
            -
                REMOTE_USER          = 'REMOTE_USER'
         | 
| 38 | 
            -
                REQUEST_METHOD       = Const::REQUEST_METHOD
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                def initialize(app, logger=nil)
         | 
| 41 | 
            -
                  @app = app
         | 
| 42 | 
            -
                  @logger = logger
         | 
| 43 | 
            -
                end
         | 
| 44 | 
            -
             | 
| 45 | 
            -
                def call(env)
         | 
| 46 | 
            -
                  began_at = Time.now
         | 
| 47 | 
            -
                  status, header, body = @app.call(env)
         | 
| 48 | 
            -
                  header = Util::HeaderHash.new(header)
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                  # If we've been hijacked, then output a special line
         | 
| 51 | 
            -
                  if env['rack.hijack_io']
         | 
| 52 | 
            -
                    log_hijacking(env, 'HIJACK', header, began_at)
         | 
| 53 | 
            -
                  else
         | 
| 54 | 
            -
                    ary = env['rack.after_reply']
         | 
| 55 | 
            -
                    ary << lambda { log(env, status, header, began_at) }
         | 
| 56 | 
            -
                  end
         | 
| 57 | 
            -
             | 
| 58 | 
            -
                  [status, header, body]
         | 
| 59 | 
            -
                end
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                private
         | 
| 62 | 
            -
             | 
| 63 | 
            -
                def log_hijacking(env, status, header, began_at)
         | 
| 64 | 
            -
                  now = Time.now
         | 
| 65 | 
            -
             | 
| 66 | 
            -
                  msg = HIJACK_FORMAT % [
         | 
| 67 | 
            -
                    env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR] || "-",
         | 
| 68 | 
            -
                    env[REMOTE_USER] || "-",
         | 
| 69 | 
            -
                    now.strftime(LOG_TIME_FORMAT),
         | 
| 70 | 
            -
                    env[REQUEST_METHOD],
         | 
| 71 | 
            -
                    env[PATH_INFO],
         | 
| 72 | 
            -
                    env[QUERY_STRING].empty? ? "" : "?#{env[QUERY_STRING]}",
         | 
| 73 | 
            -
                    env[HTTP_VERSION],
         | 
| 74 | 
            -
                    now - began_at ]
         | 
| 75 | 
            -
             | 
| 76 | 
            -
                  write(msg)
         | 
| 77 | 
            -
                end
         | 
| 78 | 
            -
             | 
| 79 | 
            -
                def log(env, status, header, began_at)
         | 
| 80 | 
            -
                  now = Time.now
         | 
| 81 | 
            -
                  length = extract_content_length(header)
         | 
| 82 | 
            -
             | 
| 83 | 
            -
                  msg = FORMAT % [
         | 
| 84 | 
            -
                    env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR] || "-",
         | 
| 85 | 
            -
                    env[REMOTE_USER] || "-",
         | 
| 86 | 
            -
                    now.strftime(LOG_TIME_FORMAT),
         | 
| 87 | 
            -
                    env[REQUEST_METHOD],
         | 
| 88 | 
            -
                    env[PATH_INFO],
         | 
| 89 | 
            -
                    env[QUERY_STRING].empty? ? "" : "?#{env[QUERY_STRING]}",
         | 
| 90 | 
            -
                    env[HTTP_VERSION],
         | 
| 91 | 
            -
                    status.to_s[0..3],
         | 
| 92 | 
            -
                    length,
         | 
| 93 | 
            -
                    now - began_at ]
         | 
| 94 | 
            -
             | 
| 95 | 
            -
                  write(msg)
         | 
| 96 | 
            -
                end
         | 
| 97 | 
            -
             | 
| 98 | 
            -
                def write(msg)
         | 
| 99 | 
            -
                  logger = @logger || env['rack.errors']
         | 
| 100 | 
            -
             | 
| 101 | 
            -
                  # Standard library logger doesn't support write but it supports << which actually
         | 
| 102 | 
            -
                  # calls to write on the log device without formatting
         | 
| 103 | 
            -
                  if logger.respond_to?(:write)
         | 
| 104 | 
            -
                    logger.write(msg)
         | 
| 105 | 
            -
                  else
         | 
| 106 | 
            -
                    logger << msg
         | 
| 107 | 
            -
                  end
         | 
| 108 | 
            -
                end
         | 
| 109 | 
            -
             | 
| 110 | 
            -
                def extract_content_length(headers)
         | 
| 111 | 
            -
                  value = headers[CONTENT_LENGTH] or return '-'
         | 
| 112 | 
            -
                  value.to_s == '0' ? '-' : value
         | 
| 113 | 
            -
                end
         | 
| 114 | 
            -
              end
         | 
| 115 | 
            -
            end
         |