UDPSocket#bind should interpret the empty string as INADDR_ANY, not loopback
----------------------------------------------------------------------------
Key: JRUBY-3564
URL: http://jira.codehaus.org/browse/JRUBY-3564
Project: JRuby
Issue Type: Bug
Components: Core Classes/Modules
Affects Versions: JRuby 1.2
Environment: Solaris 10 x86 and Mac OS X 10.5 Intel
Reporter: Clayton Wheeler
Attachments: udp_inaddr_any.patch
Calling UDPSocket#bind with the empty string for the address specification is
meant to signify INADDR_ANY (0.0.0.0), but in JRuby it binds to the loopback
address (127.0.0.1) instead. The RubyUDPSocket class passes the empty string to
the InetSocketAddress constructor, which interprets it as 127.0.0.1. (See
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4970439 for confirmation
that this is intentional JDK behavior.)
I noticed this because it breaks the Resolv::DNS library in JRuby. It binds a
UDP socket with the empty string; on MRI this gives it an INADDR_ANY socket
that works for queries, but on JRuby it gets a socket bound to the loopback
interface and tries to query name servers with that, which does not work. This
is a non-obvious failure mode, too; it took me half an hour with truss, pfiles,
and jstack to work out what was going on.
There is an RSpec test case for this in
spec/ruby/library/socket/udpsocket/bind_spec.rb; "binds to INADDR_ANY if the
hostname is empty". However, it currently fails for an unrelated reason;
JRuby's getsockname returns something that isn't a struct sockaddr. I have
filed JRUBY-3563 which contains a fix for that.
In the mean time, the test script included should suffice.
See the attached udp_inaddr_any.patch for a fix.
==== START test script ====
#!/usr/bin/env ruby
require 'socket'
s = UDPSocket.new()
s.bind('', 21264)
addr = s.addr[3]
if addr == '0.0.0.0'
puts "OK, got INADDR_ANY: #{s.addr.inspect}"
exit 0
else
puts "WRONG, got loopback: #{s.addr.inspect}"
end
==== END test script ====
$ ruby bind-test-case
OK, got INADDR_ANY: ["AF_INET", 21264, "0.0.0.0", "0.0.0.0"]
$ ./bin/jruby bind-test-case
WRONG, got loopback: ["AF_INET", 21264, "localhost", "127.0.0.1"]
==== With patch for JRUBY-3563, before fix ====
$ ./spec/mspec/bin/mspec run -t j
spec/ruby/library/socket/udpsocket/bind_spec.rb
jruby 1.2.0 (ruby 1.8.6 patchlevel 287) (2009-04-11 rev 9531) [i386-java]
..F
1)
UDPSocket.bind binds to INADDR_ANY if the hostname is empty FAILED
Expected "127.0.0.1"
to equal "0.0.0.0"
/Users/csw/src/jruby-1_2/spec/ruby/library/socket/udpsocket/bind_spec.rb:32
/Users/csw/src/jruby-1_2/spec/ruby/library/socket/udpsocket/bind_spec.rb:4
/Users/csw/src/jruby-1_2/spec/ruby/library/socket/udpsocket/bind_spec.rb:55:in
`load'
Finished in 0.205000 seconds
1 file, 3 examples, 4 expectations, 1 failure, 0 errors
==== With fix ====
$ ./spec/mspec/bin/mspec run -t j
spec/ruby/library/socket/udpsocket/bind_spec.rb
jruby 1.2.0 (ruby 1.8.6 patchlevel 287) (2009-04-11 rev 9531) [i386-java]
...
Finished in 0.219000 seconds
1 file, 3 examples, 4 expectations, 0 failures, 0 errors
$ ./bin/jruby bind-test-case
OK, got INADDR_ANY: ["AF_INET", 21264, "0.0.0.0", "0.0.0.0"]
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://jira.codehaus.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
---------------------------------------------------------------------
To unsubscribe from this list, please visit:
http://xircles.codehaus.org/manage_email