Skip to content

Commit 3f3c2e2

Browse files
committed
ssl: allow SSLContext#set_params to be used from non-main Ractors
Freeze OpenSSL::SSL::SSLContext::DEFAULT_PARAMS so that it becomes Ractor-shareable. Also, prepare a new OpenSSL::X509::Store in Ractor-local storage, if called from a non-main Ractor. OpenSSL::X509::Store currently is not a shareable object.
1 parent b7cde6d commit 3f3c2e2

File tree

2 files changed

+49
-2
lines changed

2 files changed

+49
-2
lines changed

lib/openssl/ssl.rb

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,10 @@ class SSLContext
6666
AES256-SHA256
6767
AES128-SHA
6868
AES256-SHA
69-
}.join(":"),
69+
}.join(":").freeze,
7070
)
7171
end
72+
DEFAULT_PARAMS.freeze
7273

7374
DEFAULT_CERT_STORE = OpenSSL::X509::Store.new # :nodoc:
7475
DEFAULT_CERT_STORE.set_default_paths
@@ -114,7 +115,14 @@ def set_params(params={})
114115
params.each{|name, value| self.__send__("#{name}=", value) }
115116
if self.verify_mode != OpenSSL::SSL::VERIFY_NONE
116117
unless self.ca_file or self.ca_path or self.cert_store
117-
self.cert_store = DEFAULT_CERT_STORE
118+
if not defined?(Ractor) or Ractor.current == Ractor.main
119+
self.cert_store = DEFAULT_CERT_STORE
120+
else
121+
self.cert_store = Ractor.current[:__openssl_default_store__] ||=
122+
OpenSSL::X509::Store.new.tap { |store|
123+
store.set_default_paths
124+
}
125+
end
118126
end
119127
end
120128
return params

test/openssl/test_ssl.rb

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2317,6 +2317,45 @@ def test_export_keying_material
23172317
end
23182318
end
23192319

2320+
# OpenSSL::Buffering requires $/ accessible from non-main Ractors (Ruby 3.5)
2321+
# https://bugs.ruby-lang.org/issues/21109
2322+
#
2323+
# Hangs on Windows
2324+
# https://bugs.ruby-lang.org/issues/21537
2325+
if respond_to?(:ractor) && RUBY_VERSION >= "3.5" && RUBY_PLATFORM !~ /mswin|mingw/
2326+
ractor
2327+
def test_ractor_client
2328+
start_server { |port|
2329+
s = Ractor.new(port, @ca_cert) { |port, ca_cert|
2330+
sock = TCPSocket.new("127.0.0.1", port)
2331+
begin
2332+
ssl = OpenSSL::SSL::SSLSocket.new(sock)
2333+
ssl.connect
2334+
ssl.puts("abc")
2335+
ssl.gets
2336+
ensure
2337+
ssl.close
2338+
sock.close
2339+
end
2340+
}.value
2341+
assert_equal("abc\n", s)
2342+
}
2343+
end
2344+
2345+
ractor
2346+
def test_ractor_set_params
2347+
# We cannot actually test default stores in the test suite as it depends
2348+
# on the environment, but at least check that it does not raise an
2349+
# exception
2350+
ok = Ractor.new {
2351+
ctx = OpenSSL::SSL::SSLContext.new
2352+
ctx.set_params
2353+
ctx.cert_store.kind_of?(OpenSSL::X509::Store)
2354+
}.value
2355+
assert(ok, "ctx.cert_store is an instance of OpenSSL::X509::Store")
2356+
end
2357+
end
2358+
23202359
private
23212360

23222361
def server_connect(port, ctx = nil)

0 commit comments

Comments
 (0)