FULL PRODUCT VERSION :
java version "1.6.0_17"
Java(TM) SE Runtime Environment (build 1.6.0_17-b04)
Java HotSpot(TM) Server VM (build 14.3-b01, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux xxxxxx.yyyy.com 2.6.18-128.1.14.el5 #1 SMP Mon Jun 1 15:52:58 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux
Red Hat Enterprise Linux Client release 5.3 (Tikanga)
(seems to affect all redhat-based linuxes, 32- and 64-bit. debian-based linuxes seem immune)
EXTRA RELEVANT SYSTEM CONFIGURATION :
/etc/hosts:
127.0.0.1 localhost.localdomain localhost xxxxxx
::1 localhost.localdomain localhost xxxxxx
/sbin/ifconfig summary:
eth0 Link encap:Ethernet HWaddr 00:10:18:34:xx:xx
inet addr:10.0.x.x Bcast:10.0.255.255 Mask:255.255.0.0
inet6 addr: fe80::210:18ff:fe34:xxxx/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
vmnet1 Link encap:Ethernet HWaddr 00:50:56:C0:00:01
inet addr:192.168.223.1 Bcast:192.168.223.255 Mask:255.255.255.0
inet6 addr: fe80::250:56ff:fec0:1/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
vmnet8 Link encap:Ethernet HWaddr 00:50:56:C0:00:08
inet addr:172.16.244.1 Bcast:172.16.244.255 Mask:255.255.255.0
inet6 addr: fe80::250:56ff:fec0:8/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
A DESCRIPTION OF THE PROBLEM :
When stdin is connected to a socket (in particular, a FILE socket), IPv6 is completely unavailable in Java.
We noticed that when we invoked java as an immediate command from ssh, as in
ssh host 'java ClassName'
it would not talk to certain server software that, due to an obscure DNS configuration, was only listening on the IPv6 loopback (rather than both the IPv4 and IPv6 loopbacks).
For some reason, this seems to affect all the Redhat-based linuxes I have tested (64-bit, 32-bit, and 32-bit vm on 64-bit kernel) and does not seem to affect the Debian-based linuxes I have tested.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
The easiest way to reproduce the condition of stdin being connected to a FILE socket is to run Java as an immediate command through ssh, like
$ ssh localhost 'java IPv6Test'
java.net.preferIPv4Stack=null
IPv6 is not working! Protocol family unavailable
If I use my bash shell to redirect stdin from a file or pipe on the other end, there is no problem:
$ ssh localhost 'java IPv6Test < /dev/null'
java.net.preferIPv4Stack=null
IPv6 seems to be working
$ ssh localhost 'echo | java IPv6Test'
java.net.preferIPv4Stack=null
IPv6 seems to be working
Or I can use ssh to connect stdin to a pseudo-tty, (mimicking what happens if you log in with ssh):
$ ssh -t localhost 'java IPv6Test'
java.net.preferIPv4Stack=null
IPv6 seems to be working
Connection to localhost closed.
The test class is simple in that it uses a failed connection to determine whether IPv6 is available, but this problem certainly prevents making connections.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Availability of IPv6 should not depend on what kind of io/file stdin is connected to.
ACTUAL -
Availability of IPv6 depends on what kind of io/file stdin is connected to, even when stdin is never read.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
You can actually see in the strace where it is detecting whether stdin (fd=0) is connected to a socket (or not):
getsockname(0, {sa_family=AF_FILE, path=""}, [17150529334688088066]) = 0
vs.
getsockname(0, 0xf7f28240, [17148559009851113500]) = -1 ENOTSOCK (Socket operation on non-socket)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.net.*;
public class IPv6Test {
public static void main(String[] args) throws Exception {
System.out.println("java.net.preferIPv4Stack=" + System.getProperty("java.net.preferIPv4Stack"));
try {
new Socket("::1", 29876).close(); // IPv6 loopback, on port unlikely to be listening
// someone was listening and we connected and closed
System.out.println("IPv6 seems to be working");
} catch (ConnectException e) {
// tried to connect, but no one was listening--what we expect
System.out.println("IPv6 seems to be working");
} catch (SocketException e) {
// some other problem connecting
System.out.println("IPv6 is not working! " + e.getMessage());
} catch (UnknownHostException e) {
// doesn't understand IPv6 loopback "::1"
System.out.println("IPv6 is not available");
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
With an ssh immediate command, using the -t parameter is a suitable work-around, because it will connect stdin to a pseudo-tty rather than a socket.
java version "1.6.0_17"
Java(TM) SE Runtime Environment (build 1.6.0_17-b04)
Java HotSpot(TM) Server VM (build 14.3-b01, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux xxxxxx.yyyy.com 2.6.18-128.1.14.el5 #1 SMP Mon Jun 1 15:52:58 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux
Red Hat Enterprise Linux Client release 5.3 (Tikanga)
(seems to affect all redhat-based linuxes, 32- and 64-bit. debian-based linuxes seem immune)
EXTRA RELEVANT SYSTEM CONFIGURATION :
/etc/hosts:
127.0.0.1 localhost.localdomain localhost xxxxxx
::1 localhost.localdomain localhost xxxxxx
/sbin/ifconfig summary:
eth0 Link encap:Ethernet HWaddr 00:10:18:34:xx:xx
inet addr:10.0.x.x Bcast:10.0.255.255 Mask:255.255.0.0
inet6 addr: fe80::210:18ff:fe34:xxxx/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
vmnet1 Link encap:Ethernet HWaddr 00:50:56:C0:00:01
inet addr:192.168.223.1 Bcast:192.168.223.255 Mask:255.255.255.0
inet6 addr: fe80::250:56ff:fec0:1/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
vmnet8 Link encap:Ethernet HWaddr 00:50:56:C0:00:08
inet addr:172.16.244.1 Bcast:172.16.244.255 Mask:255.255.255.0
inet6 addr: fe80::250:56ff:fec0:8/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
A DESCRIPTION OF THE PROBLEM :
When stdin is connected to a socket (in particular, a FILE socket), IPv6 is completely unavailable in Java.
We noticed that when we invoked java as an immediate command from ssh, as in
ssh host 'java ClassName'
it would not talk to certain server software that, due to an obscure DNS configuration, was only listening on the IPv6 loopback (rather than both the IPv4 and IPv6 loopbacks).
For some reason, this seems to affect all the Redhat-based linuxes I have tested (64-bit, 32-bit, and 32-bit vm on 64-bit kernel) and does not seem to affect the Debian-based linuxes I have tested.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
The easiest way to reproduce the condition of stdin being connected to a FILE socket is to run Java as an immediate command through ssh, like
$ ssh localhost 'java IPv6Test'
java.net.preferIPv4Stack=null
IPv6 is not working! Protocol family unavailable
If I use my bash shell to redirect stdin from a file or pipe on the other end, there is no problem:
$ ssh localhost 'java IPv6Test < /dev/null'
java.net.preferIPv4Stack=null
IPv6 seems to be working
$ ssh localhost 'echo | java IPv6Test'
java.net.preferIPv4Stack=null
IPv6 seems to be working
Or I can use ssh to connect stdin to a pseudo-tty, (mimicking what happens if you log in with ssh):
$ ssh -t localhost 'java IPv6Test'
java.net.preferIPv4Stack=null
IPv6 seems to be working
Connection to localhost closed.
The test class is simple in that it uses a failed connection to determine whether IPv6 is available, but this problem certainly prevents making connections.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Availability of IPv6 should not depend on what kind of io/file stdin is connected to.
ACTUAL -
Availability of IPv6 depends on what kind of io/file stdin is connected to, even when stdin is never read.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
You can actually see in the strace where it is detecting whether stdin (fd=0) is connected to a socket (or not):
getsockname(0, {sa_family=AF_FILE, path=""}, [17150529334688088066]) = 0
vs.
getsockname(0, 0xf7f28240, [17148559009851113500]) = -1 ENOTSOCK (Socket operation on non-socket)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.net.*;
public class IPv6Test {
public static void main(String[] args) throws Exception {
System.out.println("java.net.preferIPv4Stack=" + System.getProperty("java.net.preferIPv4Stack"));
try {
new Socket("::1", 29876).close(); // IPv6 loopback, on port unlikely to be listening
// someone was listening and we connected and closed
System.out.println("IPv6 seems to be working");
} catch (ConnectException e) {
// tried to connect, but no one was listening--what we expect
System.out.println("IPv6 seems to be working");
} catch (SocketException e) {
// some other problem connecting
System.out.println("IPv6 is not working! " + e.getMessage());
} catch (UnknownHostException e) {
// doesn't understand IPv6 loopback "::1"
System.out.println("IPv6 is not available");
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
With an ssh immediate command, using the -t parameter is a suitable work-around, because it will connect stdin to a pseudo-tty rather than a socket.
- relates to
-
JDK-8211842 IPv6_supported wrongly returns false when unix domain socket is bound to fd 0
-
- Resolved
-