Quintus/ruby-xz

ruby-xz breaks Resolv.getaddress in ruby 2.2.x

kensimon opened this issue · 8 comments

Reproducible pretty trivially:

Gemfile:

source 'https://rubygems.org'
gem 'ruby-xz'

test.rb

#!/usr/bin/env ruby
require 'resolv'
require 'xz'
puts Resolv.getaddress('google.com')
$ bundle exec ./test.rb
/Users/ken/.rbenv/versions/2.2.3/lib/ruby/2.2.0/resolv.rb:905:in `initialize': wrong number of arguments (2 for 0..1) (ArgumentError)
    from /Users/ken/.rbenv/versions/2.2.3/lib/ruby/2.2.0/resolv.rb:929:in `new'
    from /Users/ken/.rbenv/versions/2.2.3/lib/ruby/2.2.0/resolv.rb:929:in `parse_resolv_conf'
    from /Users/ken/.rbenv/versions/2.2.3/lib/ruby/2.2.0/resolv.rb:961:in `default_config_hash'
    from /Users/ken/.rbenv/versions/2.2.3/lib/ruby/2.2.0/resolv.rb:982:in `block in lazy_initialize'

Looks like what's happening is that resolv.rb is calling an unqualified "open", which is probably expected to call "File.open"... but instead it ends up calling "DNS.open" (which calls DNS.new), which doesn't have the same argument count.

I think it may be something in the io-like gem that's being mixed in and monkey patching something, such that ruby's method resolution order is changed.

I think it's a deeper issue here in the io-like gem that calling include IO::Like tends to poison the method resolution order for lots of IO stuff in newer rubies (their github page says they don't even support 1.9.x yet.) I think the fix is to get off of io-like altogether.

Weird. I just tested your script, and I can reproduce the problem. However, I don’t think it is related to io-like, because this works as intended:

#!/usr/bin/env ruby
require 'resolv'
require "io/like"
puts Resolv.getaddress('google.com')
$ ruby -v
ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-linux]

This will require some debugging. Thanks for reporting!

Vale,
Quintus

Oh yes. Such a great bug. This was the cause:

class XZ::StreamReader < XZ::Stream
  # ...
  self.class.send(:alias_method, :open, :new)
  # ...
end

What this intended to do is to alias a class method. However, self is XZ::StreamReader in this context (the class object), so self.class is Class (the Ruby class for class objects). So what the code really did was redefining Class#open, which in turn seems to have quite nasty side effects.

However, it appears I accidentally fixed the problem already in commit a4ec945, where I removed that statement and replaced it with an explicit method definition, because I wanted to add a deprecation warning for a certain use of that alias. So, could you please test with current devel again? If you need a gem, you can run rake gem to build one.

Vale,
Quintus

After running bundle clean, I was able to verify this bug is fixed with the following Gemfile:

source 'https://rubygems.org'
ruby '2.2.0'
gem 'ruby-xz', :git => 'https://github.com/Quintus/ruby-xz.git', :ref => '48e1fe2f2898056275eba73725d6e0df0eefb0dd'

Thanks for the fix! Looking forward to the released gem :)

Okay, thanks for testing. It will be included into the next release 0.2.2 then.

Vale,
Quintus

Do you have an ETA for a 0.2.2 release?

Thanks for reminding me. I just released 0.2.2 and pushed it to rubygems.org.

Happy coding!

Vale,
Quintus

Thanks!

Due to a documentation error, I also released 0.2.3. The source code of 0.2.2 and 0.2.3 is otherwise identical.

Vale,
Quintus