Skip to content

Commit eb17479

Browse files
committed
Make OpenSSL::Digest subclasses Ractor-safe
Replace define_method with class_eval string eval for initialize, digest, and hexdigest on the dynamically-created Digest subclasses (SHA1, SHA256, etc.). The lambda passed to define_method captures a local variable, making it non-shareable and preventing the method from being called in non-main Ractors.
1 parent 036ed68 commit eb17479

1 file changed

Lines changed: 12 additions & 9 deletions

File tree

ext/openssl/lib/openssl/digest.rb

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,19 @@ def self.digest(name, data)
2727
end
2828

2929
%w(MD4 MD5 RIPEMD160 SHA1 SHA224 SHA256 SHA384 SHA512).each do |name|
30-
klass = Class.new(self) {
31-
define_method(:initialize, ->(data = nil) {super(name, data)})
32-
}
30+
klass = Class.new(self)
31+
# Use class_eval with a string so the initialize method is not
32+
# defined via define_method with a Proc (which is not Ractor-safe).
33+
klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1
34+
def initialize(data = nil)
35+
super("#{name}", data)
36+
end
37+
RUBY
3338

34-
singleton = (class << klass; self; end)
35-
36-
singleton.class_eval{
37-
define_method(:digest) {|data| new.digest(data)}
38-
define_method(:hexdigest) {|data| new.hexdigest(data)}
39-
}
39+
klass.singleton_class.class_eval <<-RUBY, __FILE__, __LINE__ + 1
40+
def digest(data) = new.digest(data)
41+
def hexdigest(data) = new.hexdigest(data)
42+
RUBY
4043

4144
const_set(name.tr('-', '_'), klass)
4245
end

0 commit comments

Comments
 (0)