hc-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Dmitry Potapov (JIRA)" <j...@apache.org>
Subject [jira] [Created] (HTTPASYNC-67) NPE on premature response from server
Date Tue, 11 Feb 2014 08:23:19 GMT
Dmitry Potapov created HTTPASYNC-67:
---------------------------------------

             Summary: NPE on premature response from server
                 Key: HTTPASYNC-67
                 URL: https://issues.apache.org/jira/browse/HTTPASYNC-67
             Project: HttpComponents HttpAsyncClient
          Issue Type: Improvement
    Affects Versions: 4.0 Final
         Environment: Linux 3.10.25-gentoo
            Reporter: Dmitry Potapov
            Priority: Minor


Steps to reproduce:
1. Bind server socket
2. Create CloseableHttpAsyncClient with .setDefaultMaxPerRoute(1);
3. Send two GET requests to port, store each Future<HttpResponse> somewhere
4. Sleep 100 ms (don't know why, but issues is not reproducible without this sleep)
5. On server socket accept incoming connection and write "HTTP/1.1 200 OK\r\nContent-Length:
0\r\nConnection: keep-alive\r\n\r\n" to socket three times
6. Call .get() on both Futures from step 3.

Expected result:
Both .get()s returns valid HttpResponse with status code 200.
or
First .get() throws exception indicating protocol violation (as Content-Length is 0)

Actual result:
First .get() returns HttpResponse with status code 200.
Second .get() throws java.util.concurrent.ExecutionException: java.lang.NullPointerException
        at org.apache.http.concurrent.BasicFuture.getResult(BasicFuture.java:70)
        at org.apache.http.concurrent.BasicFuture.get(BasicFuture.java:80)
        at NPETest.main(NPETest.java:46)
Caused by: java.lang.NullPointerException
        at org.apache.http.impl.nio.client.MainClientExec.responseReceived(MainClientExec.java:318)
        at org.apache.http.impl.nio.client.DefaultClientExchangeHandlerImpl.responseReceived(DefaultClientExchangeHandlerImpl.java:148)
        at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.responseReceived(HttpAsyncRequestExecutor.java:227)
        at org.apache.http.impl.nio.client.LoggingAsyncRequestExecutor.responseReceived(LoggingAsyncRequestExecutor.java:112)
        at org.apache.http.impl.nio.DefaultNHttpClientConnection.consumeInput(DefaultNHttpClientConnection.java:256)
        at org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:73)
        at org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:37)
        at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:116)
        at org.apache.http.impl.nio.reactor.BaseIOReactor.validate(BaseIOReactor.java:219)
        at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:282)
        at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:106)
        at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:589)
        at java.lang.Thread.run(Thread.java:744)

NPE is not too informative and probably there should be IOException or HttpException instead.
Most probably this error occurs because no events comes to reactor after first response consumption.

Here the simple program illustrating the issue:
import java.net.ServerSocket;
import java.net.Socket;

import java.nio.charset.StandardCharsets;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;

public class NPETest {
    public static void main(final String... args) throws Exception {
        ServerSocket server = new ServerSocket(0, 1);
        PoolingNHttpClientConnectionManager connManager =
            new PoolingNHttpClientConnectionManager(
                new DefaultConnectingIOReactor());
        connManager.setDefaultMaxPerRoute(1);
        connManager.setMaxTotal(Integer.MAX_VALUE);
        try (CloseableHttpAsyncClient client = HttpAsyncClients.custom()
                .setConnectionManager(connManager)
                .build())
        {   
            client.start();
            List<Future<HttpResponse>> requests = new ArrayList<>();
            for (int i = 0; i < 2; ++i) {
                requests.add(client.execute(
                    new HttpGet("http://localhost:" + server.getLocalPort()),
                    null));
            }
            Socket socket = server.accept();
            System.out.println(
                System.currentTimeMillis() + " Accepted");
            Thread.sleep(100);
            for (int i = 0; i < 3; ++i) {
                socket.getOutputStream().write(("HTTP/1.1 200 OK\r\n"
                    + "Content-Length: 0\r\nConnection: keep-alive\r\n\r\n")
                        .getBytes(StandardCharsets.UTF_8));
            }
            for (Future<HttpResponse> request: requests) {
                System.out.println("Response: " + request.get());
            }
        }
    }
}



--
This message was sent by Atlassian JIRA
(v6.1.5#6160)

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


Mime
View raw message