aboutsummaryrefslogtreecommitdiffstats
path: root/actioncable/lib/action_cable/server/base.rb
diff options
context:
space:
mode:
authorMatthew Draper <matthew@trebex.net>2016-01-25 03:53:27 +1030
committerMatthew Draper <matthew@trebex.net>2016-01-30 03:46:37 +1030
commit16a6603956551703e3bbd06101c568a73bcdaa52 (patch)
treee11ead941c881d3a58956ee5f80e91e1702ac89c /actioncable/lib/action_cable/server/base.rb
parenta928aa3d3f1e6f8780acc22d69f4d5d1f5917926 (diff)
downloadrails-16a6603956551703e3bbd06101c568a73bcdaa52.tar.gz
rails-16a6603956551703e3bbd06101c568a73bcdaa52.tar.bz2
rails-16a6603956551703e3bbd06101c568a73bcdaa52.zip
Synchronize the lazy setters in Server
They're all at risk of races on the first requests.
Diffstat (limited to 'actioncable/lib/action_cable/server/base.rb')
-rw-r--r--actioncable/lib/action_cable/server/base.rb23
1 files changed, 16 insertions, 7 deletions
diff --git a/actioncable/lib/action_cable/server/base.rb b/actioncable/lib/action_cable/server/base.rb
index b00abd208c..fe48c112df 100644
--- a/actioncable/lib/action_cable/server/base.rb
+++ b/actioncable/lib/action_cable/server/base.rb
@@ -1,3 +1,5 @@
+require 'thread'
+
module ActionCable
module Server
# A singleton ActionCable::Server instance is available via ActionCable.server. It's used by the rack process that starts the cable server, but
@@ -13,7 +15,12 @@ module ActionCable
def self.logger; config.logger; end
delegate :logger, to: :config
+ attr_reader :mutex
+
def initialize
+ @mutex = Mutex.new
+
+ @remote_connections = @stream_event_loop = @worker_pool = @channel_classes = @pubsub = nil
end
# Called by rack to setup the server.
@@ -29,29 +36,31 @@ module ActionCable
# Gateway to RemoteConnections. See that class for details.
def remote_connections
- @remote_connections ||= RemoteConnections.new(self)
+ @remote_connections || @mutex.synchronize { @remote_connections ||= RemoteConnections.new(self) }
end
def stream_event_loop
- @stream_event_loop ||= ActionCable::Connection::StreamEventLoop.new
+ @stream_event_loop || @mutex.synchronize { @stream_event_loop ||= ActionCable::Connection::StreamEventLoop.new }
end
# The thread worker pool for handling all the connection work on this server. Default size is set by config.worker_pool_size.
def worker_pool
- @worker_pool ||= ActionCable::Server::Worker.new(max_size: config.worker_pool_size)
+ @worker_pool || @mutex.synchronize { @worker_pool ||= ActionCable::Server::Worker.new(max_size: config.worker_pool_size) }
end
# Requires and returns a hash of all the channel class constants keyed by name.
def channel_classes
- @channel_classes ||= begin
- config.channel_paths.each { |channel_path| require channel_path }
- config.channel_class_names.each_with_object({}) { |name, hash| hash[name] = name.constantize }
+ @channel_classes || @mutex.synchronize do
+ @channel_classes ||= begin
+ config.channel_paths.each { |channel_path| require channel_path }
+ config.channel_class_names.each_with_object({}) { |name, hash| hash[name] = name.constantize }
+ end
end
end
# Adapter used for all streams/broadcasting.
def pubsub
- @pubsub ||= config.pubsub_adapter.new(self)
+ @pubsub || @mutex.synchronize { @pubsub ||= config.pubsub_adapter.new(self) }
end
# All the identifiers applied to the connection class associated with this server.