Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Avoid the constant redefinition warning
The gem and bundle commands first load digest via openssl, so loading the digest gem would cause this warning every time one of these commands is run: ``` .../lib/ruby/gems/3.0.0/gems/digest-3.1.0/lib/digest.rb:11: warning: already initialized constant Digest::REQUIRE_MUTEX .../lib/ruby/3.0.0/digest.rb:7: warning: previous definition of REQUIRE_MUTEX was here ```
- Loading branch information
1617261
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@knu May I ask how this can be reproduced? Does it happen with the latest bundler and/or rubygems? I think it's not a good practice to allow two potentially different copies of the same gem to be mixed together so this warning is a good indication that some issue is happening. I'd like to fix the real culprit instead
1617261
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@deivid-rodriguez Sure, build the gem without this change and install it, then run any gem command and you'll get the redefinition error. This is because the rubygem library requires
openssl
which pulls indigest
via the OpenSSL::Digest module and the newly installed digest gem is loaded after the digest library is loaded.1617261
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So do
OpenSSL::Digest
andDigest
are different implementations of the same functionality. Which one is preferred?1617261
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If
OpenSSL::Digest
does what we need, this patch to rubygems should do the trick and avoid the double load1617261
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I understand the problem better now. I think the problem is that
openssl
requiresdigest
from the C-extension, so thatrequire
is ruby's built-inrequire
which doesn't includerubygems
decorations to be able to activate gems, resulting in the default version ofdigest
being required but not activated as a gem.While the above patch avoids the issue for usages of
gem
, if end users activate thedigest
gem, they will get the same error I believe. I think a better solution would be to changeopenssl
to requiredigest
from ruby, so that the proper version is activated as a gem.1617261
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you got the situation correctly. Actually, OpenSSL::Digest is built with/on top of the digest API so it is not an option to stop requiring
digest
, but you could possibly change theopenssl
library so thatopenssl/digest
is a separate module with autoload enabled, triggered by using OpenSSL::Digest. I haven't yet looked into it closely, though.1617261
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'm going to introduce the patch in rubygems anyways to not require
digest
explicitly and letopenssl
deal with that instead, so you might want to revert this commit. But I'll also look into fixing this in general insideopenssl
. Thanks!1617261
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Loading
openssl
after installing adigest
gem already bringsdigest
into a broken state:My first thought was to simply declare
digest
as a runtime dependency inopenssl
's gemspec, but that won't work because RubyGems activates dependency gems immediately only when exactly one matching version is installed on the system. TIL...Agreed.
1617261
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, although that will be fixed by rubygems/rubygems#4979. But even with that, if any user code that tries to load
digest
, the issue will reappear.Indeed! Still, in my opinion explicitly declaring dependencies is a good practice, although not everybody agrees there: https://bugs.ruby-lang.org/issues/16951.
1617261
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@knu Changes have been introduced to both
openssl
andrubygems
to avoid this issue. Should we revert this commit now?1617261
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fix in
openssl
happened in ruby/openssl#463 and it's included in openssl gem 2.1.3/2.2.1.I think this should be reverted -- the warning in the commit message shows that
digest
is in an inconsistent state and the user should know that.1617261
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, but does these fixes apply to already released ruby versions?
1617261
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, but
digest
is not a default gem in those rubies, so I don't think the warning can happen there.1617261
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean I'm sure you'll see the warning with Ruby version 3.0.[0-2]. The warning would only be likely to occur either while running a gem/bundle command or rubygems/bundler went wrong somehow, so I think it is just annoying more than it is helpful. I just hope the fixes will be part of 3.0.3 and 3.1.0, and I'll add a version guard and limit the hack to 3.0.[0-2].
1617261
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, you're right,
digest
is a default gem since ruby 3.0. Your plan sounds good to me! As far as I understand, ruby 3.0.3 will include openssl 2.2.1, so it should be all good.1617261
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I forgot to say thank you so much for your effort! It is much appreciated.