Skip to content

Commit

Permalink
Use actual thread local for Puma::Server.current. (#3360)
Browse files Browse the repository at this point in the history
* Add test for `Puma::Server.current`.

* Use actual thread local for `Puma::Server.current`.
  • Loading branch information
ioquatix committed Apr 24, 2024
1 parent 7a999de commit 3169cf6
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 3 deletions.
8 changes: 5 additions & 3 deletions lib/puma/server.rb
Expand Up @@ -18,6 +18,9 @@

module Puma

# This method was private on Ruby 2.4 but became public on Ruby 2.5+:
Thread.send(:attr_accessor, :puma_server)

# The HTTP Server itself. Serves out a single Rack app.
#
# This class is used by the `Puma::Single` and `Puma::Cluster` classes
Expand Down Expand Up @@ -47,7 +50,6 @@ class Server
attr_accessor :app
attr_accessor :binder

THREAD_LOCAL_KEY = :puma_server

# Create a server for the rack app +app+.
#
Expand Down Expand Up @@ -131,7 +133,7 @@ def inherit_binder(bind)
class << self
# @!attribute [r] current
def current
Thread.current[THREAD_LOCAL_KEY]
Thread.current.puma_server
end

# :nodoc:
Expand Down Expand Up @@ -438,7 +440,7 @@ def handle_check
# Return true if one or more requests were processed.
def process_client(client)
# Advertise this server into the thread
Thread.current[THREAD_LOCAL_KEY] = self
Thread.current.puma_server = self

clean_thread_locals = options[:clean_thread_locals]
close_socket = true
Expand Down
45 changes: 45 additions & 0 deletions test/test_puma_server_current.rb
@@ -0,0 +1,45 @@
# frozen_string_literal: true

# Released under the MIT License.
# Copyright, 2023, by Samuel Williams.

require_relative "helper"

require "puma/server"

class PumaServerCurrentApplication
def call(env)
[200, {"Content-Type" => "text/plain"}, [Puma::Server.current.to_s]]
end
end

class PumaServerCurrentTest < Minitest::Test
parallelize_me!

def setup
@tester = PumaServerCurrentApplication.new
@server = Puma::Server.new @tester, nil, {log_writer: Puma::LogWriter.strings, clean_thread_locals: true}
@port = (@server.add_tcp_listener "127.0.0.1", 0).addr[1]
@tcp = "http://127.0.0.1:#{@port}"
@url = URI.parse(@tcp)
@server.run
end

def teardown
@server.stop(true)
end

def test_clean_thread_locals
server_string = @server.to_s
responses = []

# This must be a persistent connection to hit the `clean_thread_locals` code path.
Net::HTTP.new(@url.host, @url.port).start do |connection|
3.times do
responses << connection.get("/").body
end
end

assert_equal [server_string]*3, responses
end
end

0 comments on commit 3169cf6

Please sign in to comment.