Error in Sys::Host on FreeBSD

Lloyd Zusman ljz@asfast.com writes:

[ … ]

The error occurs when I run the test.rb program with the final line
uncommented, as follows:

#!/usr/bin/ruby

require "sys/host"
include Sys

puts Host.hostname
puts Host.ip_addr
Host.ip_addr{|ip| puts ip}

I just discovered that if I use “each” in the final line, the
error goes
away …

Host.ip_addr.each {|ip| puts ip}

I’m not sure if the final line in test.rb has a typo, or if
this a bona
fide bug because the ip_addr method is supposed to properly handle
iterators.

That’s interesting. It should work without the each method. I just
tested it on Solaris using an August build of 1.7.2 and it worked ok.
However, I have not tested it against 1.7.2 on FreeBSD. I must also admit
that I’ve never actually tested this on a system with more than 1 IP address

  • I simply don’t have access to a system that does.

BTW, which compiler? What version of FreeBSD? Which version of Sys::Host?

So, there are a few possibilities:

  1. This only shows up in recent builds of 1.7.x
  2. This only shows up in 1.7.x on FreeBSD
  3. Old compiler
  4. Some memory isn’t being freed that should be (or vice versa)

I’ll attempt to test this as soon as I get access to a FreeBSD system again
with 1.7.x. Even better - someone gives me access to a FreeBSD system with
multiple ethernet cards. :slight_smile:

Regards,

Daniel Berger

That's interesting. It *should* work without the each method. I just
tested it on Solaris using an August build of 1.7.2 and it worked ok.
However, I have not tested it against 1.7.2 on FreeBSD. I must also admit
that I've never actually tested this on a system with more than 1 IP address
- I simply don't have access to a system that does.

pigeon% cat test.rb
#!/usr/bin/ruby

require "sys/host"
include Sys

puts Host.hostname
puts Host.ip_addr
Host.ip_addr{|ip| puts ip}
pigeon%

pigeon% ruby test.rb
pigeon
138.102.114.46
138.102.114.46
test.rb:8: [BUG] Segmentation fault
ruby 1.6.7 (2002-03-01) [i686-linux]
Aborted
pigeon%

The segmentation fault is for free()

The difference between the call with or without an block is that you
call `host_free(pptr);' when it's called as an iterator.

Guy Decoux

The error was raised on FreeBSD release and current.

I scanned host.c and found the function host_free() looks needless
unless I misunderstand. And ip_addr() doesn’t return any value when
it is called as an iterator.

By the way, two comments about host.c…

You wrote
Host.ip_addr.each do |ip| # multi-nic system
but one has to use something platform dependent, e.g., ifconfig (or
ipconfig on ms-windows) to know all addresses of a machine, afaik.
getbyhostname() or getaddrinfo() do only reverse lookup for a name of
host but not all interfaces are associated often to the name given
by hostname().

I think that use of Socket is not overkill to get michine’s addresses
because Socket has getaddrinfo() which resolves protocol-independently.
It seems pretty hard to provide getaddrinfo() or an equivalent
function for various platforms where the function is missing.

So, a lazy person’s shows another Sys::Host below :slight_smile:
This is IPv6 ready,

require "socket"
module Sys
module Host
include Socket::Constants
module_function

  def hostname
    Socket::gethostname()
  end

  def ip_addr(af = AF_UNSPEC, serv = nil, &block)
    addrs = Socket.getaddrinfo(Socket::gethostname(), serv, af)
    addrs.map!{|i| i[3]}
    addrs.uniq!
    return addrs unless block_given?
    addrs.each(&block)
  end
end

end

if FILE == $0
puts "hostname: #{Sys::Host::hostname}"
puts "IP addresses: #{Sys::Host::ip_addr.join(’, ')}"
Sys::Host::ip_addr{|i| puts “==> #{i}”}
end

– Gotoken

···

At Fri, 20 Sep 2002 22:14:39 +0900, Berger, Daniel djberge@qwest.com wrote:

That’s interesting. It should work without the each method. I just
tested it on Solaris using an August build of 1.7.2 and it worked ok.