JDK-4258193 : java.net.InetAddress#getByName() deadlocks
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 1.1,1.1.1,1.1.4,1.2.2
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS:
    generic,solaris_2.5.1,solaris_2.6, ... generic,solaris_2.5.1,solaris_2.6,windows_95,windows_nt
  • CPU: generic,x86,sparc
  • Submitted: 1999-07-29
  • Updated: 1999-09-29
  • Resolved: 1999-09-29
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
1.3.0 kestrelFixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Description
Name: krT82822			Date: 07/29/99


In JDK 1.2.2, getHostByName() method of InetAddress class deadlocks.

This is a simple miscoding for thread synchronization but this is a very serious bug for the network programming. Please fix this bug quickly.

For example, one thread gets the lock of an addressCache instance (1) and tries to get the lock of InetAddressCachePolicy class (2) in order to get an IP address from an address cache.
The sun.net.InetAddressCachePolicy#get() method is a synchronized method.

    private static Object getCachedAddress(String hostname) {
        hostname = hostname.toLowerCase();
	synchronized (addressCache) { // (1)
	    if (InetAddressCachePolicy.get() == 0) { // (2)
		return null;
	    }

And another thread gets the lock of InetAddressCachePolicy class and tries to get the lock of an addressCache instance in order to register an IP address to an address cache.

    private static void cacheAddress(String hostname, Object address) {
	synchronized (InetAddressCachePolicy.class) { // (3)
	// if the cache policy is to cache nothing, just return
	    if (InetAddressCachePolicy.get() == 0) {
		return;
	    }
	    long expiration = -1;
	    if (InetAddressCachePolicy.get() != InetAddressCachePolicy.FOREVER) {
		expiration = System.currentTimeMillis() + 
		    (InetAddressCachePolicy.get() * 1000);
	    }
	    cacheAddress(hostname, address, expiration);
	}
    }

    private static void cacheAddress(String hostname, Object address, long expiration) {
        hostname = hostname.toLowerCase();
	synchronized (addressCache) { // (4)

Then they are deadlocked.

-----------

7/29/99 kevin.ryan@eng -- submitting as-is
(Review ID: 88440) 
======================================================================

Name: skT88420			Date: 09/10/99


I am running a DNS name resolver with between 1-30 threads performing concurrent name resolution.  This code snip below runs in a class derived from thread.  A stream of "hostAddr" addresses are fed to the thread and the results are placed into a table.

   ia = InetAddress.getByName( hostAddr ) ;
   hostName = ia.getHostName() ;

Sometimes, (1 in 3, or 1 in 4 cases ) the threads become deadlocked in java.net.InetAddress:src line 328

326:    private static Object getCachedAddress(String hostname) {
327:        hostname = hostname.toLowerCase();
328:	synchronized (addressCache) {
329:	    if (InetAddressCachePolicy.get() == 0) {
330:		return null;
331:	    }

The problem is more common as the thread count increases.  It is quite easily produced with 40 threads.  The lockup should occur within a few hundred dns requests.  When I found the issue and began investigating the src file, I was horrified to find a cache that grows without bounds.  Since I will be processing 100,000(s) of InetAddress in a Session this cache would have become a large issue.

(1) Fix the deadlock Issue

(2) make public the existance of the cache, and the sun.net.inetaddr.ttl property.  The fact that you need to browse the java.net.InetAddress file to find the sun.net.InetAddressCachePolicy and then disassemble with javap to find the existance of the property is insufficient.  It at least deserves a note in the JavaDoc for InetAddress.
(Review ID: 95113)
======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: generic FIXED IN: kestrel INTEGRATED IN: kestrel
14-06-2004

WORK AROUND Name: krT82822 Date: 07/29/99 We made the following fixes for InetAddress class. *** InetAddress.java.old Tue Jul 27 15:18:03 1999 --- InetAddress.java Tue Jul 27 15:21:48 1999 *************** *** 295,312 **** } private static void cacheAddress(String hostname, Object address) { - synchronized (InetAddressCachePolicy.class) { // if the cache policy is to cache nothing, just return ! if (InetAddressCachePolicy.get() == 0) { ! return; ! } ! long expiration = -1; ! if (InetAddressCachePolicy.get() != InetAddressCachePolicy.FOREVER) { ! expiration = System.currentTimeMillis() + ! (InetAddressCachePolicy.get() * 1000); ! } ! cacheAddress(hostname, address, expiration); } } private static void cacheAddress(String hostname, Object address, long expiration) { --- 295,310 ---- } private static void cacheAddress(String hostname, Object address) { // if the cache policy is to cache nothing, just return ! int policy = InetAddressCachePolicy.get(); ! if (policy == 0) { ! return; } + long expiration = -1; + if (policy != InetAddressCachePolicy.FOREVER) { + expiration = System.currentTimeMillis() + (policy * 1000); + } + cacheAddress(hostname, address, expiration); } private static void cacheAddress(String hostname, Object address, long expiration) { *************** *** 325,334 **** private static Object getCachedAddress(String hostname) { hostname = hostname.toLowerCase(); synchronized (addressCache) { - if (InetAddressCachePolicy.get() == 0) { - return null; - } CacheEntry entry = (CacheEntry)addressCache.get(hostname); if (entry != null && entry.expiration < System.currentTimeMillis() && entry.expiration >= 0) { --- 323,332 ---- private static Object getCachedAddress(String hostname) { hostname = hostname.toLowerCase(); + if (InetAddressCachePolicy.get() == 0) { + return null; + } synchronized (addressCache) { CacheEntry entry = (CacheEntry)addressCache.get(hostname); if (entry != null && entry.expiration < System.currentTimeMillis() && entry.expiration >= 0) { ====================================================================== Name: skT88420 Date: 09/10/99 Use the "sun.net.inetaddr.ttl=0" property. (Review ID: 95113) ======================================================================
11-06-2004

EVALUATION Agree with what is suggested in the workaround. yingxian.wang@eng 1999-09-22
22-09-1999