Project

General

Profile

Actions

Bug #963

closed

/opt/local/lib/ruby/1.8/drb/drb.rb:852:in `initialize': getaddrinfo: nodename nor servname provided, or not known (SocketError)

Added by charl (Charl Matthee) about 15 years ago. Updated over 4 years ago.

Status:
Closed
Target version:
-
ruby -v:
1.8, 1.9
[ruby-core:21033]

Description

=begin
There are two issues here:

  1. The DRb code in drb.rb does not correctly deal with multiple network families if they're present.
  2. TCPServer.open(port) where port == 0 fails on OS X but not Linux.

When you run the following DRb client code you get the error in the Summary:

#!/usr/bin/env ruby -KU

require 'rubygems'
require 'thread'
require 'drb'

Thread.abort_on_exception = true
DRb.start_service
q = DRbObject.new_with_uri('druby://127.0.0.1:3491')
loop do
q.push("Hello from #{Process.pid} at #{Time.now}", rand(10))
sleep 1
end
exit

The source in question is (/opt/local/lib/ruby/1.8/drb/drb.rb:852):

 def self.open_server_inaddr_any(host, port)
   infos = Socket::getaddrinfo(host, nil,
                               Socket::AF_UNSPEC,
                               Socket::SOCK_STREAM,                                  0,
                               Socket::AI_PASSIVE)
   family = infos.collect { |af, *_| af }.uniq
   case family
   when ['AF_INET']
     return TCPServer.open('0.0.0.0', port)
   when ['AF_INET6']
     return TCPServer.open('::', port)
   else
     return TCPServer.open(port)
   end
 end

On my MacBook Pro the Socket::getaddrinfo() above returns the following (where hostname == 'localhost'):

[["AF_INET6", 0, "localhost", "::1", 30, 1, 6], ["AF_INET6",
0, "localhost", "fe80::1%lo0", 30, 1, 6], ["AF_INET", 0, "localhost",
"127.0.0.1", 2, 1, 6]]

The family assignment and case block are written to assume that you'll generally have only one network family in the
family variable. Deviations to this fall through to call the following code (where port == 0) from that block which
is where the error occurs:

return TCPServer.open(port)

TCPServer.open(port) where port == 0 seems to fail on OS X:

$ irb
irb(main):001:0> require "socket"
=> true
irb(main):002:0> port = 0
=> 0
irb(main):003:0> TCPServer.open(port)
SocketError: getaddrinfo: nodename nor servname provided, or not known
from (irb):3:in initialize' from (irb):3:in open'
from (irb):3
from :0
irb(main):004:0>

But the same works on Linux:

$ irb
irb(main):001:0> require "socket"
=> true
irb(main):002:0> port = 0
=> 0
irb(main):003:0> TCPServer.open(port)
=> #TCPServer:0xb7c37f78
irb(main):004:0>

The patch below simply fixes /opt/local/lib/ruby/1.8/drb/drb.rb (issue #1 above) by treating the network families as
a list and trying 'AF_INET' and 'AF_INET6' in succession and then falling through to TCPServer.open(port) if no families
matched:

$ diff /opt/local/lib/ruby/1.8/drb/drb.rb ~/Desktop/drb.rb-new
845,853c845,848
< family = infos.collect { |af, *_| af }.uniq
< case family
< when ['AF_INET']
< return TCPServer.open('0.0.0.0', port)
< when ['AF_INET6']
< return TCPServer.open('::', port)
< else
< return TCPServer.open(port)
< end

  families = Hash[*infos.collect { |af, *_| af }.uniq.zip([]).flatten]
  return TCPServer.open('0.0.0.0', port) if families.has_key?('AF_INET')
  return TCPServer.open('::', port) if families.has_key?('AF_INET6')
  return TCPServer.open(port)

866c861
< soc = TCPServer.open(host, port)

  soc = TCPServer.open(host,  port)

A further patch may be required to deal with the different way in which OS X responds to TCPServer.open(0) (issue #2
above).
=end

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0