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

Thread leak when calling LdapContext.reconnect

XMLWordPrintable

      A DESCRIPTION OF THE PROBLEM :
      When being connected to a domain controller using LDAP the javax.naming library creates a reader thread in order to receive the response from the server.
      Calling the reconnect method on the LdapContext instance performs a reconnect and creates a new reader thread. However, it does not stop the old reader thread from the previous connection. That leads to a resource leak, because with every reconnect call, a new thread gets created and the old threads are not being stopped.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Open a LDAP connection:

      env = new Hashtable<String, String>();
          env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
          env.put (Context.SECURITY_PRINCIPAL, username);
          env.put (Context.SECURITY_CREDENTIALS, password);
          
          if((this.security == SecurityProtocol.NONE) || (this.security == SecurityProtocol.TLS)) {
            env.put(Context.PROVIDER_URL, String.format ("ldap://%s:%d", this.hostname, this.port));
          }
          else if(this.security == SecurityProtocol.LDAPS) {
            env.put(Context.PROVIDER_URL, String.format ("ldaps://%s:%d", this.hostname, this.port));
            env.put(Context.SECURITY_PROTOCOL, "ssl");
            env.put("java.naming.ldap.factory.socket", "com.jdisc.inventory.protocols.ldap.LdapSslSocketFactory");
          }
          else {
            throw new IllegalArgumentException("Illegal security setting");
          }
         
          env.put("java.naming.ldap.attributes.binary", "objectGUID objectSID");
          env.put(CONNECT_TIMEOUT_KEY, Integer.toString (connectTimeout));
          env.put(READ_TIMEOUT_KEY, Integer.toString (readTimeout));
          
          connCtls = new Control[] {new FastBindConnectionControl()};
          ctx = new InitialLdapContext(env, connCtls);
          
          if(this.security == SecurityProtocol.TLS) {
            StartTlsResponse tls = (StartTlsResponse) ctx.extendedOperation(new StartTlsRequest());
            tls.setHostnameVerifier (new LdapHostnameVerifier());
            tls.negotiate(new LdapSslSocketFactory());
          }

       // This creates the additional thread and the original reader thread never stops.
        ctx.reconnect();

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The reconnect method should either reuse the existing thread or first stop the existing thread and then create the new reader-thread.
      ACTUAL -
      After the reconnect method, we have two reader threads for the same connection. One of them will never disappear. Even when you disconnect the LDAP context.

      ---------- BEGIN SOURCE ----------
      env = new Hashtable<String, String>();
          env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
          env.put (Context.SECURITY_PRINCIPAL, username);
          env.put (Context.SECURITY_CREDENTIALS, password);
          
          if((this.security == SecurityProtocol.NONE) || (this.security == SecurityProtocol.TLS)) {
            env.put(Context.PROVIDER_URL, String.format ("ldap://%s:%d", this.hostname, this.port));
          }
          else if(this.security == SecurityProtocol.LDAPS) {
            env.put(Context.PROVIDER_URL, String.format ("ldaps://%s:%d", this.hostname, this.port));
            env.put(Context.SECURITY_PROTOCOL, "ssl");
            env.put("java.naming.ldap.factory.socket", "com.jdisc.inventory.protocols.ldap.LdapSslSocketFactory");
          }
          else {
            throw new IllegalArgumentException("Illegal security setting");
          }
         
          env.put("java.naming.ldap.attributes.binary", "objectGUID objectSID");
          env.put(CONNECT_TIMEOUT_KEY, Integer.toString (connectTimeout));
          env.put(READ_TIMEOUT_KEY, Integer.toString (readTimeout));
          
          connCtls = new Control[] {new FastBindConnectionControl()};
          ctx = new InitialLdapContext(env, connCtls);
          
          if(this.security == SecurityProtocol.TLS) {
            StartTlsResponse tls = (StartTlsResponse) ctx.extendedOperation(new StartTlsRequest());
            tls.setHostnameVerifier (new LdapHostnameVerifier());
            tls.negotiate(new LdapSslSocketFactory());
          }

      // The reconnect causes the issue.
       ctx.reconnect();
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      No workaround known when reconnect required.

      FREQUENCY : always


            psonal Pallavi Sonal (Inactive)
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: