Repository: puma/puma
File: lib/puma/request.rb (Ruby)

Code before:
      end
      prepare_response(status, headers, res_body, requests, client)
    ensure
      io_buffer.reset
      uncork_socket client.io
      app_body.close if app_body.respond_to? :close
      client&.tempfile_close
      if after_reply = env[RACK_AFTER_REPLY]
        after_reply.each do |o|
          begin
            o.call
          rescue StandardError => e
            @log_writer.debug_error e
          end
        end
      end

      if response_finished = env[RACK_RESPONSE_FINISHED]
        response_finished.reverse_each do |o|
          begin
            o.call
          rescue StandardError => e
            @log_writer.debug_error e
          end
        end
      end
    end

    # Assembles the headers and prepares the body for actually sending the
    # response via `#fast_write_response`.
    #
    # @param status [Integer] the status returned by the Rack application
    # @param headers [Hash] the headers returned by the Rack application
    # @param res_body [Array] the body returned by the Rack application or
    #   a call to `Server#lowlevel_error`
    # @param requests [Integer] number of inline requests handled
    # @param client [Puma::Client]
    # @return [Boolean,:async] keep-alive status or `:async`
    def prepare_response(status, headers, res_body, requests, client)
      env = client.env
      socket = client.io
      io_buffer = client.io_buffer

      return false if closed_socket?(socket)

      # Close the connection after a reasonable number of inline requests
      # if the server is at capacity and the listener has a new connection ready.
      # This allows Puma to service connections fairly when the number
      # of concurrent connections exceeds the size of the threadpool.
      force_keep_alive = if @enable_keep_alives
        requests < @max_fast_inline ||

Review comment (bug):
```suggestion
      response_finished.reverse_each do |o|
        begin
          o.call
        rescue StandardError => e
          @log_writer.debug_error e
        end
      end
```

Code after:
        status, headers, res_body = lowlevel_error(error, env, 500)
      end
      prepare_response(status, headers, res_body, requests, client)
    ensure
      io_buffer.reset
      uncork_socket client.io
      app_body.close if app_body.respond_to? :close
      client&.tempfile_close
      if after_reply = env[RACK_AFTER_REPLY]
        after_reply.each do |o|
          begin
            o.call
          rescue StandardError => e
            @log_writer.debug_error e
          end
        end
      end

      if response_finished = env[RACK_RESPONSE_FINISHED]
        response_finished.reverse_each do |o|
          begin
            o.call(env, status, headers, error)
          rescue StandardError => e
            @log_writer.debug_error e
          end
        end
      end
    end

    # Assembles the headers and prepares the body for actually sending the
    # response via `#fast_write_response`.
    #
    # @param status [Integer] the status returned by the Rack application
    # @param headers [Hash] the headers returned by the Rack application
    # @param res_body [Array] the body returned by the Rack application or
    #   a call to `Server#lowlevel_error`
    # @param requests [Integer] number of inline requests handled
    # @param client [Puma::Client]
    # @return [Boolean,:async] keep-alive status or `:async`
    def prepare_response(status, headers, res_body, requests, client)
      env = client.env
      socket = client.io
      io_buffer = client.io_buffer

      return false if closed_socket?(socket)

      # Close the connection after a reasonable number of inline requests
      force_keep_alive = @enable_keep_alives && client.requests_served < @max_keep_alive

      resp_info = str_headers(env, status, headers, res_body, io_buffer, force_keep_alive)