Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoiding "already initialized constant errors" with net/protocol #16

Closed
stanhu opened this issue Mar 18, 2021 · 19 comments
Closed

Avoiding "already initialized constant errors" with net/protocol #16

stanhu opened this issue Mar 18, 2021 · 19 comments

Comments

@stanhu
Copy link

stanhu commented Mar 18, 2021

If I have a gem that depends on net/imap v0.2.1, I see that it conflicts with the Ruby interpreter's version:

$ bundle exec rspec spec
/home/travis/.rvm/rubies/ruby-2.6.6/lib/ruby/2.6.0/net/protocol.rb:66: warning: already initialized constant Net::ProtocRetryError
/home/travis/.rvm/gems/ruby-2.6.6/gems/net-protocol-0.1.0/lib/net/protocol.rb:66: warning: previous definition of ProtocRetryError was here
/home/travis/.rvm/rubies/ruby-2.6.6/lib/ruby/2.6.0/net/protocol.rb:206: warning: already initialized constant Net::BufferedIO::BUFSIZE
/home/travis/.rvm/gems/ruby-2.6.6/gems/net-protocol-0.1.0/lib/net/protocol.rb:206: warning: previous definition of BUFSIZE was here
/home/travis/.rvm/rubies/ruby-2.6.6/lib/ruby/2.6.0/net/protocol.rb:503: warning: already initialized constant Net::NetPrivate::Socket
/home/travis/.rvm/gems/ruby-2.6.6/gems/net-protocol-0.1.0/lib/net/protocol.rb:503: warning: previous definition of Socket was here

Is there a way this updated version of the gem can be used as a separate dependency without generating these warnings? https://stackoverflow.com/a/9117903/1992201 has some suggestions, but these still seem like hacks. Does it make sense to remove net/protocol as a hard dependency? MRI appears to have an exact copy of protocol.rb.

stanhu added a commit to stanhu/net-imap that referenced this issue Mar 18, 2021
Attempting to use an updated net/imap as a separate dependency causes
"already initalized constant errors":

```shell
$ bundle exec rspec spec
/home/travis/.rvm/rubies/ruby-2.6.6/lib/ruby/2.6.0/net/protocol.rb:66: warning: already initialized constant Net::ProtocRetryError
/home/travis/.rvm/gems/ruby-2.6.6/gems/net-protocol-0.1.0/lib/net/protocol.rb:66: warning: previous definition of ProtocRetryError was here
/home/travis/.rvm/rubies/ruby-2.6.6/lib/ruby/2.6.0/net/protocol.rb:206: warning: already initialized constant Net::BufferedIO::BUFSIZE
/home/travis/.rvm/gems/ruby-2.6.6/gems/net-protocol-0.1.0/lib/net/protocol.rb:206: warning: previous definition of BUFSIZE was here
/home/travis/.rvm/rubies/ruby-2.6.6/lib/ruby/2.6.0/net/protocol.rb:503: warning: already initialized constant Net::NetPrivate::Socket
/home/travis/.rvm/gems/ruby-2.6.6/gems/net-protocol-0.1.0/lib/net/protocol.rb:503: warning: previous definition of Socket was here
```

This happens because MRI already includes its own implementation of
net/protocol, and this dependency causes a redefinition of the same
file.

Closes ruby#16
@shugo
Copy link
Member

shugo commented Mar 19, 2021

net/protocol and net/imap have been default gems since Ruby 3.0, so it may introduce problems to remove net-protocol from dependencies.
On Ruby 2.6, net/imap itself is not a (default) gem, so it may be hard to use the net-imap gem without hacks.

@hsbt What do you think?

@deivid-rodriguez
Copy link

@stanhu I'm interested in this is issue. Can you share steps to reproduce the warnings?

@stanhu
Copy link
Author

stanhu commented Mar 19, 2021

@deivid-rodriguez The easiest way I've been able to reproduce it:

git clone git@github.com:tpitale/mail_room.git
cd mail_room
echo 2.7.2 > .ruby_version # Choose your version
bundle install
bundle exec rspec spec/lib/mailbox_spec.rb

@deivid-rodriguez
Copy link

Thanks, I'll have a look!

@deivid-rodriguez
Copy link

The proper fix here in my opinion would be that the faraday-net_http gem would declare the net-http gem as a dependency.

This is the explanation of what's happening:

  • When the faraday-net_http gem is required, it then requires net/http.
  • Then the stdlib version of net/http is loaded, since bundler doesn't know net-http is a gem dependency, so it doesn't add the gemified version to to the $LOAD_PATH.
  • Then the stdlib version of net/http requires net/protocol relatively, since that's what it used to happen before these gems were gemified. See ruby/net-http@6da598e. So the stdlib version of net/protocol is loaded.
  • Then when net-imap is required, it also uses net-protocol but this time the gemified version of net-protocol is used, because net-imap properly declares it as a dependency, so bundler knows about it and has put it in the $LOAD_PATH. This is what causes the double load of net/protocol.

If faraday-net_http explicitly declares net-http as a dependency, then the gemified version of all gems involved will be consistently loaded and there will be no redefinition warnings.

I suggest that you proposed this update to faraday-net_http and in the mean time, you can workaround this issue by adding gem "net-http" to your Gemfile.

stanhu added a commit to stanhu/faraday-net_http that referenced this issue Mar 19, 2021
As described in https://www.ruby-lang.org/en/news/2020/12/25/ruby-3-0-0-released/, Ruby
3.0.0 promoted net-http from stdlib. Adding this as a dependency avoids
"aleady initialized constant errors" if net-imap or some other gem is
included. See ruby/net-imap#16 (comment) for
more details.
stanhu added a commit to stanhu/mail_room that referenced this issue Mar 19, 2021
As described in https://www.ruby-lang.org/en/news/2020/12/25/ruby-3-0-0-released/, Ruby
3.0.0 promoted net-http and net-imap from stdlib. Adding net-http as a
dependency avoids "already initialized constant errors" if net-imap or
some other gem is included. See
ruby/net-imap#16 (comment) for
more details.
stanhu added a commit to stanhu/faraday-net_http that referenced this issue Mar 19, 2021
As described in https://www.ruby-lang.org/en/news/2020/12/25/ruby-3-0-0-released/, Ruby
3.0.0 promoted net-http from stdlib. Adding this as a dependency avoids
"already initialized constant errors" if net-imap or some other gem is
included. See ruby/net-imap#16 (comment) for
more details.
@stanhu stanhu changed the title Avoiding "aleady initialized constant errors" with net/protocol Avoiding "already initialized constant errors" with net/protocol Mar 19, 2021
@stanhu
Copy link
Author

stanhu commented Mar 19, 2021

@deivid-rodriguez Thanks for that tip! That seems to work well. I've submitted lostisland/faraday-net_http#5 and tpitale/mail_room#123.

@stanhu stanhu closed this as completed Mar 19, 2021
stanhu added a commit to stanhu/faraday-net_http that referenced this issue Mar 19, 2021
As described in https://www.ruby-lang.org/en/news/2020/12/25/ruby-3-0-0-released/, Ruby
3.0.0 promoted net-http from stdlib. Adding this as a dependency avoids
"already initialized constant errors" if net-imap or some other gem is
included. See ruby/net-imap#16 (comment) for
more details.
@stanhu
Copy link
Author

stanhu commented Mar 19, 2021

One issue is that net-http requires Ruby 2.6, so older Rubies won't work with this add_dependency.

@hsbt
Copy link
Member

hsbt commented Mar 19, 2021

It's not related dependencies of gemspec.

@deivid-rodriguez
Copy link

One issue is that net-http requires Ruby 2.6, so older Rubies won't work with this add_dependency.

Oh, I see, that's unfortunate. I guess you need to workaround this via Gemfile until other dependencies also drop Ruby 2.5 support :(. For what it's worth, ruby 2.5 was dropped at ruby/net-http@e6ab6d7. My guess is that the only reason was that CI didn't pass.

stanhu added a commit to stanhu/mail_room that referenced this issue Mar 21, 2021
As described in https://www.ruby-lang.org/en/news/2020/12/25/ruby-3-0-0-released/, Ruby
3.0.0 promoted net-http and net-imap from stdlib. Adding net-http as a
dependency avoids "already initialized constant errors" if net-imap and
faraday are used.  See
ruby/net-imap#16 (comment) for
more details.
@deivid-rodriguez
Copy link

Cointidentially I run into a similar instance of this issue myself today. To make things easier for gem authors and motivate them to add the dependency, I propose to release at least one gemified version of net-http that supports ruby 2.5. I proposed that at ruby/net-http#19.

ctln12 added a commit to ctln12/rails-ticketee that referenced this issue Jan 17, 2022
thatbudakguy added a commit to sul-dlss/sul-directory that referenced this issue Jan 31, 2022
This avoids the "already initialized constant" errors that
evidently result from faraday's dependencies requiring
two different versions of net-protocol. For discussion see:
ruby/net-imap#16 (comment)
@iMacTia
Copy link

iMacTia commented Apr 17, 2023

Hi @deivid-rodriguez, I'd like to chime in on the discussion since I've been asked multiple times to add net-http as a dependency tofaraday-net_http as a result of your comment and I'm not completely sure yet if that's the correct thing to do.

I explained my understanding of the issue in this comment and why I believe it is a mistake to add these gems explicitly in gemspec.

If faraday were to add net-http as a dependency, it would force every project using it to switch to the gemified version of the libray. This would be OK on Ruby 3.0, but it might be a disaster for previous rubies, where the stdlib version is still present.

For example, I'd expect issues like this to pop up if I did that.

I'm not sure why some gems have started adding explicit dependencies to these gems, but it seems like letting Ruby figuring it out by itself (when to use the stdlib or the standard gem) is the best way to avoid this mix and match and support both Rubies older and newer than 3.0.

I understand some people are affected by this issue because they use a gem that has added one of these dependencies to their gemspec, and I can see why it's annoying to now having to add more dependencies themselves.
But as I see it, if I were to add the same dependency to faraday this could actually increase the conflicts rather than improving the situation.

It would be great to discuss this and agree to a solution that could benefit everyone 🙏

@deivid-rodriguez
Copy link

deivid-rodriguez commented Apr 17, 2023

Sorry I don't have a lot of time to look into this right now, but I can say something similar to this has been discussed in the upstream Ruby tracker, and there's no agreement. For example, https://bugs.ruby-lang.org/issues/16951. Note that I did propose ruby/net-http#19 after that message you mention to avoid this problem, but it didn't happen.

Not sure about your specific situation and the range of rubies where issues would pop up vs the range of rubies that would benefit from it. If this would only cause problems on rubies that have reached EOL, and those problems are only warnings, then I do think it's worth prioritizing users of supported rubies. But you know best what makes more sense for your libraries, and of course you can chime in the core tracker and propose any solutions. As I said, I don't have a lot of time right now, sorry :(

@iMacTia
Copy link

iMacTia commented Apr 17, 2023

This is great context, thank you @deivid-rodriguez.
Glad to hear there's some discussion ongoing, I'd definitely like to get to the bottom of this before releasing any change in Faraday that could potentially make things even worse

@deivid-rodriguez
Copy link

No problem, sorry I can't help more right now, and I appreciate your conciousness and will to get to the bottom of things.

@voxik
Copy link
Contributor

voxik commented Apr 17, 2023

it would force every project using it to switch to the gemified version of the libray.

This is very vague claim and might or might not be true. It very much depends on the context.

it might be a disaster for previous rubies, where the stdlib version is still present.

This is overstatement. Generally, there is nothing wrong in using gemified version of library in old Ruby. The net-http gem supports Ruby 2.6+, so unless you talk about way older versions of Ruby, then it should be just fine.

@deivid-rodriguez
Copy link

Right, I'm still unclear about the issue with newer rubies. There's many moving parts so there could be some issue, I just don't know what it is right now.

As I have pointed out in other places, adding explicit dependencies helps Bundler and RubyGems provide consistent results. And also helps users because the exact gem version is recorded in the lockfile just like any other dependency, so you get consistent results when using the dependency even if you switch rubies.

evolve2k added a commit to demingfactor/calagator that referenced this issue Apr 20, 2023
ponelat added a commit to ponelat/askanybook that referenced this issue Apr 27, 2023
rjpaskin added a commit to CorporateRewards/flight_plan that referenced this issue May 15, 2023
Due to us being on Ruby 2.7 and faraday-net_http not having a dependency
on the `net-http` default gem (to maintain Ruby 2.5 compatibility) - see
ruby/net-imap#16. Issue should go away on Ruby
3.
@gepinedo
Copy link

gepinedo commented Oct 3, 2023

The proper fix here in my opinion would be that the faraday-net_http gem would declare the net-http gem as a dependency.
This is the explanation of what's happening:

  • When the faraday-net_http gem is required, it then requires net/http.
  • Then the stdlib version of net/http is loaded, since bundler doesn't know net-http is a gem dependency, so it doesn't add the gemified version to to the $LOAD_PATH.
  • Then the stdlib version of net/http requires net/protocol relatively, since that's what it used to happen before these gems were gemified. See ruby/net-http@6da598e. So the stdlib version of net/protocol is loaded.
  • Then when net-imap is required, it also uses net-protocol but this time the gemified version of net-protocol is used, because net-imap properly declares it as a dependency, so bundler knows about it and has put it in the $LOAD_PATH. This is what causes the double load of net/protocol.

If faraday-net_http explicitly declares net-http as a dependency, then the gemified version of all gems involved will be consistently loaded and there will be no redefinition warnings.
I suggest that you proposed this update to faraday-net_http and in the mean time, you can workaround this issue by adding gem "net-http" to your Gemfile.

thank you, I resolved the problem

Thanks, @deivid-rodriguez, it works perfectly!

aspiers added a commit to aspiers/swapmyvote that referenced this issue Jun 9, 2024
aspiers added a commit to aspiers/swapmyvote that referenced this issue Jun 9, 2024
aspiers added a commit to aspiers/swapmyvote that referenced this issue Jun 14, 2024
aspiers added a commit to aspiers/swapmyvote that referenced this issue Jun 15, 2024
aspiers added a commit to aspiers/swapmyvote that referenced this issue Jun 15, 2024
aspiers added a commit to aspiers/swapmyvote that referenced this issue Jun 15, 2024
aspiers added a commit to aspiers/swapmyvote that referenced this issue Jun 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

9 participants