Issue #8159 has been updated by naruse (Yui NARUSE). I create an experimental patch as following for failures on Linux: http://u64.rubyci.org/~chkbuild/ruby-trunk/log/20130324T210202Z.log.html.gz diff --git a/ext/socket/socket.c b/ext/socket/socket.c index 1ddaea9..44703c1 100644 --- a/ext/socket/socket.c +++ b/ext/socket/socket.c @@ -1585,7 +1585,9 @@ socket_s_ip_address_list(VALUE self) for (p = ifp; p; p = p->ifa_next) { if (p->ifa_addr != NULL && IS_IP_FAMILY(p->ifa_addr->sa_family)) { struct sockaddr *addr = p->ifa_addr; - rb_ary_push(list, sockaddr_obj(addr, sockaddr_len(addr))); + ai = sockaddr_obj(addr, sockaddr_len(addr)); + rb_ivar_set(ai, rb_intern("@ifa_name"), rb_str_new_cstr(p->ifa_name)); + rb_ary_push(list, ai); } } @@ -1856,6 +1858,12 @@ socket_s_ip_address_list(VALUE self) #define socket_s_ip_address_list rb_f_notimplement #endif +VALUE +sock_s_if_nametoindex(VALUE klass, VALUE name) +{ + return UINT2NUM(if_nametoindex(StringValueCStr(name))); +} + void Init_socket() { @@ -1999,6 +2007,7 @@ Init_socket() rb_define_singleton_method(rb_cSocket, "gethostbyaddr", sock_s_gethostbyaddr, -1); rb_define_singleton_method(rb_cSocket, "getservbyname", sock_s_getservbyname, -1); rb_define_singleton_method(rb_cSocket, "getservbyport", sock_s_getservbyport, -1); + rb_define_singleton_method(rb_cSocket, "if_nametoindex", sock_s_if_nametoindex, 1); rb_define_singleton_method(rb_cSocket, "getaddrinfo", sock_s_getaddrinfo, -1); rb_define_singleton_method(rb_cSocket, "getnameinfo", sock_s_getnameinfo, -1); rb_define_singleton_method(rb_cSocket, "sockaddr_in", sock_s_pack_sockaddr_in, 2); diff --git a/lib/rinda/ring.rb b/lib/rinda/ring.rb index 9b3e273..b87800c 100644 --- a/lib/rinda/ring.rb +++ b/lib/rinda/ring.rb @@ -59,6 +59,8 @@ module Rinda end end + attr_accessor :multicast_interface + ## # Advertises +ts+ on the given +addresses+ at +port+. # @@ -84,6 +86,7 @@ module Rinda @w_services = write_services @r_service = reply_service + @multicast_interface = 0 end ## @@ -111,6 +114,9 @@ module Rinda mreq = IPAddr.new(addrinfo.ip_address).hton + [0].pack('I') socket.setsockopt(:IPPROTO_IPV6, :IPV6_JOIN_GROUP, mreq) + sa = addrinfo.to_sockaddr + sa[-4, 4] = [@multicast_interface].pack('I') + addrinfo = Addrinfo.new(sa) end end diff --git a/test/rinda/test_rinda.rb b/test/rinda/test_rinda.rb index 65df228..9aaeb66 100644 --- a/test/rinda/test_rinda.rb +++ b/test/rinda/test_rinda.rb @@ -525,7 +525,24 @@ class TupleSpaceProxyTest < Test::Unit::TestCase @server = DRb.primary_server || DRb.start_service end +module RingIPv6 + def prepare_ipv6(r) + Socket.ip_address_list.any? do |addrinfo| + if addrinfo.ipv6? && ipv6_global_unicast?(addrinfo) + r.multicast_interface = Socket.if_nametoindex(addrinfo.instance_variable_get(:@ifa_name)) + return + end + end + skip 'IPv6 not available' + end + + def ipv6_global_unicast?(ai) + (ai.ip_address[0].to_i & 0b1110) == 0b0010 + end +end + class TestRingServer < Test::Unit::TestCase + include RingIPv6 def setup @port = Rinda::Ring_PORT @@ -560,14 +577,8 @@ class TestRingServer < Test::Unit::TestCase end def test_make_socket_ipv6_multicast - skip 'IPv6 not available' unless - Socket.ip_address_list.any? { |addrinfo| addrinfo.ipv6? } - - begin - v6mc = @rs.make_socket('ff02::1') - rescue Errno::EADDRNOTAVAIL - return # IPv6 address for multicast not available - end + prepare_ipv6(@rs) + v6mc = @rs.make_socket('ff02::1') if Socket.const_defined?(:SO_REUSEPORT) then assert v6mc.getsockopt(:SOCKET, :SO_REUSEPORT).bool @@ -575,7 +586,7 @@ class TestRingServer < Test::Unit::TestCase assert v6mc.getsockopt(:SOCKET, :SO_REUSEADDR).bool end - assert_equal('ff02::1', v6mc.local_address.ip_address) + assert_match(/\Aff02::1(?:%|\z)/, v6mc.local_address.ip_address) assert_equal(@port, v6mc.local_address.ip_port) end @@ -588,22 +599,10 @@ class TestRingServer < Test::Unit::TestCase end class TestRingFinger < Test::Unit::TestCase + include RingIPv6 def setup @rf = Rinda::RingFinger.new - ifindex = nil - 10.times do |i| - begin - addrinfo = Addrinfo.udp('ff02::1', Rinda::Ring_PORT) - soc = Socket.new(addrinfo.pfamily, addrinfo.socktype, addrinfo.protocol) - soc.setsockopt(:IPPROTO_IPV6, :IPV6_MULTICAST_IF, - [i].pack('I')) - ifindex = i - break - rescue - end - end - @rf.multicast_interface = ifindex end def test_make_socket_unicast @@ -620,26 +619,23 @@ class TestRingFinger < Test::Unit::TestCase end def test_make_socket_ipv6_multicast - skip 'IPv6 not available' unless - Socket.ip_address_list.any? { |addrinfo| addrinfo.ipv6? } - + prepare_ipv6(@rf) v6mc = @rf.make_socket('ff02::1') assert_equal(1, v6mc.getsockopt(:IPPROTO_IPV6, :IPV6_MULTICAST_LOOP).int) assert_equal(1, v6mc.getsockopt(:IPPROTO_IPV6, :IPV6_MULTICAST_HOPS).int) end - def test_make_socket_multicast_hops + def test_make_socket_ipv4_multicast_hops @rf.multicast_hops = 2 - v4mc = @rf.make_socket('239.0.0.1') - assert_equal(2, v4mc.getsockopt(:IPPROTO_IP, :IP_MULTICAST_TTL).int) + end - return unless Socket.ip_address_list.any? { |addrinfo| addrinfo.ipv6? } - + def test_make_socket_ipv6_multicast_hops + prepare_ipv6(@rf) + @rf.multicast_hops = 2 v6mc = @rf.make_socket('ff02::1') - assert_equal(2, v6mc.getsockopt(:IPPROTO_IPV6, :IPV6_MULTICAST_HOPS).int) end ---------------------------------------- Bug #8159: Build failure introduced by Rinda changes https://bugs.ruby-lang.org/issues/8159#change-37914 Author: luislavena (Luis Lavena) Status: Assigned Priority: Normal Assignee: drbrain (Eric Hodel) Category: test Target version: next minor ruby -v: ruby 2.1.0dev (2013-03-24 trunk 39905) [x64-mingw32] =begin Seems latest Rinda-related changes affected build under Windows: http://ci.rubyinstaller.org/job/ruby-trunk-x64-test-all/936/console 2) Error: test_take_bug_8215(Rinda::TupleSpaceProxyTest): NotImplementedError: fork() function is unimplemented on this machine C:/Users/Worker/Jenkins/workspace/ruby-trunk-x64-build/test/rinda/test_rinda.rb:486:in `fork' C:/Users/Worker/Jenkins/workspace/ruby-trunk-x64-build/test/rinda/test_rinda.rb:486:in `test_take_bug_8215' 3) Error: test_make_socket_ipv4_multicast(Rinda::TestRingServer): Errno::EADDRNOTAVAIL: The requested address is not valid in its context. - bind(2) C:/Users/Worker/Jenkins/workspace/ruby-trunk-x64-build/lib/rinda/ring.rb:117:in `bind' C:/Users/Worker/Jenkins/workspace/ruby-trunk-x64-build/lib/rinda/ring.rb:117:in `make_socket' C:/Users/Worker/Jenkins/workspace/ruby-trunk-x64-build/test/rinda/test_rinda.rb:542:in `test_make_socket_ipv4_multicast' r39895 seems to have introduced a test that is not skipping on non-fork() platforms. =end -- http://bugs.ruby-lang.org/