You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@hc.apache.org by bu...@apache.org on 2004/08/06 22:58:05 UTC

DO NOT REPLY [Bug 30514] New: - HttpClient deadlocks under multithreaded access

DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://issues.apache.org/bugzilla/show_bug.cgi?id=30514>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://issues.apache.org/bugzilla/show_bug.cgi?id=30514

HttpClient deadlocks under multithreaded access

           Summary: HttpClient deadlocks under multithreaded access
           Product: Commons
           Version: 2.0 Final
          Platform: PC
        OS/Version: Windows NT/2K
            Status: NEW
          Severity: Critical
          Priority: Other
         Component: HttpClient
        AssignedTo: commons-httpclient-dev@jakarta.apache.org
        ReportedBy: neil.thier@trilogy.com


HttpClient appears to deadlock under heavy concurrent use.  I've created a
isolated test that reproduces the problem, included below.  The symptoms are
that the number of threads in use eventually reaches the total and stays there.
 This is independent of the response code.  The response time of the request
also does not appear to affect it, although it delays.

The connection pool does not seem to free up after any of the regular connection
timeout values have passed.

The ratio of threads to pool size appears to alleviate the problem if the pool
size is multiple times larger than the number of threads.

---------------------------

import java.net.URL;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.PostMethod;


/**
 * Test to reproduce the connection pool freezing problem in HttpClient.
 * 
 * When there is a lot of concurrent interaction (lots of connections being 
 * created and released) with HttpClient the connection pool eventually fills
 * and never gets cleaned out.  This causes all users of the client to then
 * be frozen.
 * 
 * This is being filed against version 2.0, but also appears to exist in
 * 3.0 alpha1 as well.
 * 
 * @author Neil Thier (c) Trilogy 2004
 */
public class MultithreadedTest {

    protected static final String TARGET = "http://localhost/some/url";
    protected static final int PORT = 8888;
    protected static final int NUM_THREADS = 10;
    protected static final int POOL_SIZE = 100;
    
    protected HttpClient m_client;
    protected URL m_serverURL;
    protected MultiThreadedHttpConnectionManager m_connMgr;

    public static void main(String[] args) throws Throwable
    {
        MultithreadedTest t = new MultithreadedTest();
        t.start( );
    }
    
    public MultithreadedTest( ) throws Throwable
    {
        // The URL to hit.
        m_serverURL = new URL( TARGET );
        
        m_connMgr = new MultiThreadedHttpConnectionManager();
        // set the per host and total the same since we're only hitting one
        m_connMgr.setMaxConnectionsPerHost( POOL_SIZE );
        m_connMgr.setMaxTotalConnections( POOL_SIZE );
        m_client = new HttpClient( m_connMgr );
        m_client.getHostConfiguration().setHost( m_serverURL.getHost(), PORT );
        m_client.setConnectionTimeout( 30000 );
        m_client.setTimeout( 30000 );
    }
    
    public void start( ) throws Throwable 
    {
        ClientThread[] threads = new ClientThread[NUM_THREADS];
        
        for ( int i = 0; i < threads.length; i++ )
        {
            threads[i] = new ClientThread( );
            Thread t = new Thread( threads[i] );
            t.start( );
        }
        
        // run forever
        for (;;) 
        {
            Thread.sleep( 1000 );
            // write out the current status so we know when it's frozen.
            // eventually the in use will equal the max and stay there
            System.out.println( "\n\rIn use: " + m_connMgr.getConnectionsInUse( ) +
                    ", max/host: " + m_connMgr.getMaxConnectionsPerHost( ) +
                    ", max total: " + m_connMgr.getMaxTotalConnections( ) );
        }
        
    }
    
    /**
     * Keep hitting a URL, with no sleep time.
     */
    class ClientThread implements Runnable 
    {
        protected Thread m_thread;
        protected boolean m_running = true;
        
        public ClientThread( )
        {
        }
        
        public void run( ) 
        {
            m_thread = Thread.currentThread( );
            try 
            {
                while ( m_running )
                {
                    PostMethod httppost = new PostMethod( m_serverURL.getPath( ) );
                    httppost.setRequestBody( "some random stuff that doesn't
matter" );
        
                    try 
                    {
                        // print out something so we know when there are active 
                        // threads
                        System.out.print( "." );
                        m_client.executeMethod( httppost );
                    } 
                    catch ( Throwable t )
                    { }
                }
            } 
            catch ( Throwable t )
            {
                t.printStackTrace( System.out );
                m_running = false;
            }
        }
    }
}

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-httpclient-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-httpclient-dev-help@jakarta.apache.org


Re: DO NOT REPLY [Bug 30514] New: - HttpClient deadlocks under multithreaded access

Posted by Eric Johnson <er...@tibco.com>.
bugzilla@apache.org wrote:

[snip]

>    /**
>     * Keep hitting a URL, with no sleep time.
>     */
>    class ClientThread implements Runnable 
>    {
>        protected Thread m_thread;
>        protected boolean m_running = true;
>        
>        public ClientThread( )
>        {
>        }
>        
>        public void run( ) 
>        {
>            m_thread = Thread.currentThread( );
>            try 
>            {
>                while ( m_running )
>                {
>                    PostMethod httppost = new PostMethod( m_serverURL.getPath( ) );
>                    httppost.setRequestBody( "some random stuff that doesn't
>matter" );
>        
>                    try 
>                    {
>                        // print out something so we know when there are active 
>                        // threads
>                        System.out.print( "." );
>                        m_client.executeMethod( httppost );
>                    } 
>                    catch ( Throwable t )
>                    { 
>
// here you should add:
httppost.releaseConnection()

>}
>                }
>            } 
>            catch ( Throwable t )
>            {
>                t.printStackTrace( System.out );
>                m_running = false;
>            }
>        }
>    }
>}
>  
>
If you don't call releaseConnection(), HttpClient doesn't know whether 
you're done reading the response to the request, so it doesn't free up 
the connection for re-use, and the MultiThreadedConnectionManager 
eventually appears to deadlock, while it is really waiting for you to 
call releaseConnection().

-Eric.


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-httpclient-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-httpclient-dev-help@jakarta.apache.org