Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-7012768

InetAddress lookupTable leaks/deadlocks when using unsupported name service spi

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P4 P4
    • 7
    • 5.0, 7
    • core-libs
    • b128
    • generic, x86
    • generic, windows_7
    • Verified

        FULL PRODUCT VERSION :
        java version "1.7.0-ea"
        Java(TM) SE Runtime Environment (build 1.7.0-ea-b125)
        Java HotSpot(TM) Client VM (build 20.0-b06, mixed mode, sharing)


        ADDITIONAL OS VERSION INFORMATION :
        Microsoft Windows [Version 6.1.7600]


        EXTRA RELEVANT SYSTEM CONFIGURATION :
        The JVM is initialized with a custom implementation of sun.net.spi.nameservice.NameService.


        A DESCRIPTION OF THE PROBLEM :
        A new functionality has been implemented in java.net.InetAddress, which serializes concurrent queries with the same lookup name on the underlying NameService.
        In any case the NameService is throwing a non-checked exception, the InetAddress's lookupTable isn't cleaned up properly.
        Further calls to InetAddress.getByName and alike with the same lookup name causes the current thread to hang forever.

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Create a custom sun.net.spi.nameservice.NameService implementation, whose "lookupAllHostAddr" method always throws a non-checked exception.

          From a Java main method, invoke 2 times in a row java.net.InetAddress.getByName with the same lookup name (i.e. "host.company.com").

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        The thread should not hang.
        In JDK6 and before, unchecked exceptions were always propagated to the caller, without further side-effects. I think keeping this behavior is the most desirable.
        ACTUAL -
        In the 1st invocation to InetAddress.getByName, the unchecked exception is propagated up to the caller, the 2nd time the thread hangs within the InetAddress.getByName invocation.

        Looking at the source code, it seems the problem would be solved if, in InetAddress.getAddressesFromNameService, the NameService iteration/cacheAddresses invocation can be wrapped in a try/finally block, with the finally block containing the updateLookupTable invocation.

        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        Client code:
        ==========
        package com.jlep.inetaddressbug;
        import java.net.*;
        public class BogusNameServiceClient
        {
          public static void main(String[] args)
          throws Exception
          {
            try {
              // First attempt - IllegalStateException catched below
              InetAddress firstAttempt = InetAddress.getByName("host.company.com");
            } catch (RuntimeException e) {
              e.printStackTrace();
            }
            // 2nd attempt
            InetAddress secondAttempt = InetAddress.getByName("host.company.com");
            // Stuck here forever
          }
        }


        Bogus NameService:
        =================
        package com.jlep.inetaddressbug;
        import java.net.*;
        import sun.net.spi.nameservice.*;
        public class BogusNameService implements NameService
        {
          public String getHostByAddr(byte[] arg0)
          throws UnknownHostException
          { throw new IllegalStateException("bogus"); }

          public InetAddress[] lookupAllHostAddr(String arg0)
          throws UnknownHostException
          { throw new IllegalStateException("bogus"); }
        }


        Related NameServiceDescriptor:
        ==========================
        package com.jlep.inetaddressbug;
        import sun.net.spi.nameservice.*;
        public class BogusNameServiceDescriptor implements NameServiceDescriptor
        {
          public NameService createNameService()
          throws Exception
          { return new BogusNameService(); }
          public String getProviderName()
          { return "Bogus"; }
          public String getType()
          { return "dns"; }
        }


        NameService descriptor file in META-INF/sun.net.spi.nameservice.NameServiceDescriptor
        ===============================================
        com.jlep.inetaddressbug.BogusNameServiceDescriptor

        JVM system properties:
        ==================
        -Dsun.net.spi.nameservice.provider.1=dns,Bogus
        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        The custom NameService implementation could wrap all internal unchecked exceptions into UnknownHostException (or a subclass).
        Adding copy of hanging stacktrace for reference purposes :
        ===

        "main" prio=3 tid=0x00025c00 nid=0x2 in Object.wait() [0xfe47f000]
           java.lang.Thread.State: WAITING (on object monitor)
                at java.lang.Object.wait(Native Method)
                - waiting on <0xe6430c70> (a java.util.HashMap)
                at java.lang.Object.wait(Object.java:502)
                at java.net.InetAddress.checkLookupTable(InetAddress.java:1299)
                - locked <0xe6430c70> (a java.util.HashMap)
                at java.net.InetAddress.getAddressFromNameService(InetAddress.java:1237)
                at java.net.InetAddress.getAllByName0(InetAddress.java:1200)
                at java.net.InetAddress.getAllByName0(InetAddress.java:1173)
                at java.net.InetAddress.getAllByName(InetAddress.java:1120)
                at java.net.InetAddress.getByName(InetAddress.java:1017)
                at Hang.main(Hang.java:44)

        ===

              chegar Chris Hegarty
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: