non-threadsafe InetAddress.getHostName()
Arne Juul
arnej at europe.yahoo-inc.com
Tue Jun 27 00:38:11 UTC 2006
We've found a problem where calls to the getHostName() method
in the java.net.InetAddress class seems to have thread-safety
problems. When two threads call this method at the same time
this may happen:
1) the first call sends a DNS query to a nameserver from port A
2) the second call sends a DNS query to a nameserver from port B
3) the answer from 1) arrives, but there isn't anything listening
on port A anymore, icmp port unreachable is generated back
4) the answer from 2) arrives on port B, second call completes
5) 5 seconds later, the query from 1) times out
6) the first call resends its DNS query from port C
7) the first call gets its answer on port C and everything looks
good (but with an extra unneeded 5 seconds delay).
This happens on FreeBSD with jdk 1.4.2p8_2 at least.
tcpdump goes approximately like this:
54.700 x.x.x.x.34683 > y.y.y.y.53: 5359+ PTR? x.x.x.x.in-addr.arpa.
54.701 x.x.x.x.34684 > y.y.y.y.53: 43030+ PTR? x.x.x.x.in-addr.arpa.
54.730 y.y.y.y.53 > x.x.x.x.34683: 5359 1/5/5 PTR foo.bar.com.
54.730 x.x.x.x > y.y.y.y: icmp: x.x.x.x udp port 34683 unreachable
54.731 y.y.y.y.53 > x.x.x.x.34684: 43030 1/5/5 PTR foo.bar.com.
59.712 x.x.x.x.34685 > y.y.y.y.53: 5359+ PTR? x.x.x.x.in-addr.arpa.
59.762 y.y.y.y.53 > x.x.x.x.34685: 5359 1/5/5 PTR foo.bar.com.
here's a test program for reproducing:
import java.net.InetAddress;
import java.lang.Thread;
import java.lang.Runnable;
class GetMyHostName {
private static class Loop implements Runnable {
long maxcnt;
Loop(long maxc) { this.maxcnt = maxc; }
public void run() {
for (long l = 0; l < maxcnt; l++) {
try {
long before = System.currentTimeMillis();
String s = InetAddress.getLocalHost().getHostName();
long after = System.currentTimeMillis();
if (after > before + 100) {
System.out.println("loop iteration "
+l
+" of "
+maxcnt
+" gethostname took: "
+(after-before)
+" milliseconds, returned: "
+s);
}
} catch (java.net.UnknownHostException e) {
}
}
}
}
public static void main(String[] args) {
try {
Loop l1 = new Loop(10001);
Loop l2 = new Loop(10002);
Loop l3 = new Loop(10003);
Thread t1 = new Thread(l1);
Thread t2 = new Thread(l2);
Thread t3 = new Thread(l3);
t1.start();
t2.start();
t3.start();
t1.join();
t2.join();
t3.join();
} catch (Exception e) {
System.out.println("exception: "+e);
}
}
}
More information about the freebsd-java
mailing list