Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 26 Jun 2006 17:38:06 -0700 (PDT)
From:      Arne Juul <arnej@europe.yahoo-inc.com>
To:        java@freebsd.org
Subject:   non-threadsafe InetAddress.getHostName()
Message-ID:  <20060626172546.P80831@dev-arnej.trondheim.corp.yahoo.com>

next in thread | raw e-mail | index | archive | help
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);
        }
    }
}




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20060626172546.P80831>