io.vertx.core.VertxException: Connection was closed - when Connection: close header in response

4,368 views
Skip to first unread message

Pavan Kumar

unread,
Mar 28, 2016, 8:22:06 AM3/28/16
to vert.x
Hi Team,

There is a related discussion with a fix at https://groups.google.com/forum/#!topic/vertx/kWw0SDCFKd4 but I am still experiencing the same exception, in a different scenario.

My use case includes a web application which issues Connection: close header when an error scenario is encountered. This is causing the connection to be closed and the next request on the same client is issued on the same connection and the exception is encountered. Sharing the stack trace and a reproducer to assist in debugging. Please assist.

Reproducer is generated with a website charcount.com which is producing the intended behavior and pool size is set to 1 to ensure the error is always reproduced.

Stacktrace:
io.vertx.core.VertxException: Connection was closed
    at io
.vertx.core.http.impl.ClientConnection.handleClosed(ClientConnection.java:305)
    at io
.vertx.core.impl.ContextImpl.lambda$wrapTask$16(ContextImpl.java:333)
    at io
.vertx.core.impl.ContextImpl.executeFromIO(ContextImpl.java:225)
    at io
.vertx.core.net.impl.VertxHandler.channelInactive(VertxHandler.java:99)
    at io
.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:208)
    at io
.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:194)
    at io
.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:306)
    at io
.netty.handler.codec.http.HttpClientCodec$Decoder.channelInactive(HttpClientCodec.java:212)
    at io
.netty.channel.CombinedChannelDuplexHandler.channelInactive(CombinedChannelDuplexHandler.java:132)
    at io
.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:208)
    at io
.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:194)
    at io
.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:828)
    at io
.netty.channel.AbstractChannel$AbstractUnsafe$7.run(AbstractChannel.java:621)
    at io
.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:358)
    at io
.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:357)
    at io
.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:112)
    at java
.lang.Thread.run(Thread.java:745)


Reproducer:
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpClientOptions;

public class HttpBug {

 
public static void main(String[] args) {
     
     
Vertx vertx = Vertx.vertx();
     
     
HttpClientOptions options = new HttpClientOptions();
      options
.setDefaultHost("charcount.com");
      options
.setMaxPoolSize(1);
     
HttpClient client = vertx.createHttpClient(options);
     
      client
.get("/404", resp -> System.out.println("Got Response. Status: "+resp.statusCode()))
         
.exceptionHandler(e -> {System.out.println("1");e.printStackTrace();}).end();
     
     
      client
.get("/404", resp -> System.out.println("Got Response. Status: "+resp.statusCode()))
         
.exceptionHandler(e -> {System.out.println("2");e.printStackTrace();}).end();
     
      vertx
.setTimer(500, t-> vertx.close());
     
 
}
}


Rob Worsnop

unread,
Mar 28, 2016, 3:38:52 PM3/28/16
to vert.x
Your reproducer is calling Vertx.close after 500 milliseconds. This is not enough time for the responses to come back from the web server.

Vertx.close will free up all resources used by Vert.x. This includes closing any connections it's created. That's what's causing the exception in this case.

Rob Worsnop

unread,
Mar 28, 2016, 4:15:12 PM3/28/16
to vert.x
Here's an "anti-reproducer":

import io.vertx.core.Vertx;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpClientOptions;

public class HttpBug {

    public static void main(String[] args) throws InterruptedException {

Vertx vertx = Vertx.vertx();

for (int i = 0; i < 2; i++){
vertx.createHttpServer().requestHandler(request->{
//request.response().putHeader("Connection","close");
request.response().end();
System.out.format("Receiving request on %s\n", Thread.currentThread().getName());
}).listen(8011);
}


Thread.sleep(500);


HttpClientOptions options = new HttpClientOptions();
        options.setDefaultHost("localhost").setDefaultPort(8011);

options.setMaxPoolSize(1);
HttpClient client = vertx.createHttpClient(options);

        for (int i = 0; i < 2; i++){
client.get("/", resp -> System.out.format("Headers: %s\n", resp.headers().entries()))
.exceptionHandler(Throwable::printStackTrace)
.end();

}

vertx.setTimer(1000, t-> {
System.out.println("closing");
vertx.close();});

}
}

If you uncomment the putHeader line, you'll see in the "Receiving request" messages that both server event loops are being used because the client is forced to create a new connection.
With that line commented, the client will keep using the same connection and the same server event loops will handle both requests.

On Monday, March 28, 2016 at 8:22:06 AM UTC-4, Pavan Kumar wrote:
Reply all
Reply to author
Forward
0 new messages