Repository: quarkusio/quarkus
Issue: io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1 when refreshing a page

**Describe the bug**
When refreshing a page that is already processing something, the following error appears in the logs:

```java
2020-07-26 21:59:17,015 WARN  [io.net.cha.AbstractChannelHandlerContext] (vert.x-eventloop-thread-8) Failed to mark a promise as failure because it has failed already: DefaultChannelPromise@3e14144f(failure: java.nio.channels.ClosedChannelException), unnotified cause: java.nio.channels.ClosedChannelException
	at io.netty.channel.AbstractChannel$AbstractUnsafe.newClosedChannelException(AbstractChannel.java:957)
	at io.netty.channel.AbstractChannel$AbstractUnsafe.write(AbstractChannel.java:865)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.write(DefaultChannelPipeline.java:1367)
	at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:717)
	at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:764)
	at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:790)
	at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:758)
	at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:767)
	at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:790)
	at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:758)
	at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:767)
	at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:790)
	at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:758)
	at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:767)
	at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:790)
	at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:758)
	at io.vertx.core.net.impl.ConnectionBase.write(ConnectionBase.java:124)
	at io.vertx.core.net.impl.ConnectionBase.lambda$queueForWrite$2(ConnectionBase.java:215)
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:834)
: io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1
	at io.netty.util.internal.ReferenceCountUpdater.toLiveRealRefCnt(ReferenceCountUpdater.java:74)
	at io.netty.util.internal.ReferenceCountUpdater.release(ReferenceCountUpdater.java:138)
	at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:100)
	at io.vertx.core.http.impl.AssembledHttpResponse.release(AssembledHttpResponse.java:159)
	at io.netty.util.ReferenceCountUtil.release(ReferenceCountUtil.java:88)
	at io.netty.channel.AbstractChannel$AbstractUnsafe.write(AbstractChannel.java:867)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.write(DefaultChannelPipeline.java:1367)
	at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:717)
	at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:764)
	at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:790)
	at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:758)
	at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:767)
	at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:790)
	at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:758)
	at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:767)
	at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:790)
	at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:758)
	at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:767)
	at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:790)
	at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:758)
	at io.vertx.core.net.impl.ConnectionBase.write(ConnectionBase.java:124)
	at io.vertx.core.net.impl.ConnectionBase.lambda$queueForWrite$2(ConnectionBase.java:215)
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:834)
```
**Expected behavior**
No error in the logs

**Actual behavior**
Error (although harmless) appears in the logs

**To Reproduce**
Steps to reproduce the behavior:
1. Clone https://github.com/gastaldi/quarkus-backports/tree/graphql
2. Go to http://localhost:8080/backports/1.1.0.Final/
3. Before the page is rendered, hit refresh in your browser. You should see the error in the logs

**Configuration**
Create an `.env` file in the project root with the following content:
```properties
BACKPORTS_TOKEN=<YOUR_GITHUB_TOKEN>

```

**Environment (please complete the following information):**
 - Output of `uname -a` or `ver`: Fedora 32 
 - Output of `java -version`: 
openjdk version "11.0.6" 2020-01-14
OpenJDK Runtime Environment 18.9 (build 11.0.6+10)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.6+10, mixed mode)

 - GraalVM version (if different from Java): Not used
 - Quarkus version or git rev: 1.6.1.Final
 - Build tool (ie. output of `mvnw --version` or `gradlew --version`): 
```
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Maven home: /home/ggastald/.m2/wrapper/dists/apache-maven-3.6.3-bin/1iopthnavndlasol9gbrbg6bf2/apache-maven-3.6.3
Java version: 11.0.6, vendor: Oracle Corporation, runtime: /home/ggastald/.sdkman/candidates/java/11.0.6-open
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "5.7.8-200.fc32.x86_64", arch: "amd64", family: "unix"
```

**Additional Context**

It happens with quarkus:dev and with java -jar too

Changed files:
extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxBlockingOutput.java
extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxHttpRequest.java
extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxRequestHandler.java
extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxOutputStream.java

diff --git a/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxBlockingOutput.java b/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxBlockingOutput.java
index 804f383dcd2..217da8e6115 100644
--- a/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxBlockingOutput.java
+++ b/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxBlockingOutput.java
@@ -106,16 +106,8 @@ public CompletionStage<Void> writeNonBlocking(ByteBuf data, boolean last) {
         } else {
             request.response().write(buffer, handler(ret));
         }
-        return ret.handle((v, t) -> {
-            if (t != null) {
-                if (data != null && data.refCnt() > 0) {
-                    data.release();
-                }
-                rethrow(new IOException("Failed to write", t));
-            }
-
-            return v;
-        });
+        //no need to free 'data', the write will handle this
+        return ret;
     }
 
     private <T extends Throwable> void rethrow(Throwable x) throws T {
diff --git a/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxHttpRequest.java b/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxHttpRequest.java
index 8f0276495e3..10a9191585c 100644
--- a/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxHttpRequest.java
+++ b/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxHttpRequest.java
@@ -9,6 +9,7 @@
 import java.util.Map;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CompletionStage;
+import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 
@@ -32,6 +33,7 @@
 import org.jboss.resteasy.spi.RunnableWithException;
 
 import io.quarkus.arc.ManagedContext;
+import io.quarkus.runtime.BlockingOperationControl;
 import io.vertx.core.Context;
 import io.vertx.ext.web.RoutingContext;
 
@@ -56,6 +58,7 @@ public final class VertxHttpRequest extends BaseHttpRequest {
     private final Context context;
     private final ManagedContext requestContext;
     private final ManagedContext.ContextState requestContextState;
+    private final Executor executor;
 
     public VertxHttpRequest(Context context,
             RoutingContext routingContext,
@@ -64,8 +67,11 @@ public VertxHttpRequest(Context context,
             String httpMethod,
             LazyHostSupplier remoteHost,
             SynchronousDispatcher dispatcher,
-            VertxHttpResponse response, ManagedContext requestContext) {
+            VertxHttpResponse response,
+            ManagedContext requestContext,
+            Executor executor) {
         super(uri);
+        this.executor = executor;
         this.context = context;
         this.response = response;
         this.httpHeaders = httpHeaders;
@@ -309,7 +315,16 @@ public void complete() {
                     done = true;
                     requestContext.activate(requestContextState);
                     requestContext.terminate();
-                    vertxFlush();
+                    if (BlockingOperationControl.isBlockingAllowed()) {
+                        vertxFlush();
+                    } else {
+                        executor.execute(new Runnable() {
+                            @Override
+                            public void run() {
+                                vertxFlush();
+                            }
+                        });
+                    }
                 }
             }
 
diff --git a/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxOutputStream.java b/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxOutputStream.java
index c82387d3bba..ea3e339db0d 100644
--- a/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxOutputStream.java
+++ b/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxOutputStream.java
@@ -177,11 +177,7 @@ public CompletionStage<Void> asyncWrite(final byte[] b, final int off, final int
             if (!buffer.isWritable()) {
                 ByteBuf tmpBuf = buffer;
                 this.pooledBuffer = buffer = allocator.allocateBuffer();
-                ret = ret.thenCompose(v -> response.writeNonBlocking(tmpBuf, false)
-                        .whenComplete((v2, t) -> {
-                            if (t != null)
-                                tmpBuf.release();
-                        }));
+                ret = ret.thenCompose(v -> response.writeNonBlocking(tmpBuf, false));
             }
         }
         return ret.thenCompose(v -> asyncUpdateWritten(len));
diff --git a/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxRequestHandler.java b/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxRequestHandler.java
index bc0f301a3b1..8f6a97b66bd 100644
--- a/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxRequestHandler.java
+++ b/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxRequestHandler.java
@@ -124,7 +124,7 @@ private void dispatch(RoutingContext routingContext, InputStream is, VertxOutput
 
             VertxHttpRequest vertxRequest = new VertxHttpRequest(ctx, routingContext, headers, uriInfo, request.rawMethod(),
                     hostSupplier,
-                    dispatcher.getDispatcher(), vertxResponse, requestContext);
+                    dispatcher.getDispatcher(), vertxResponse, requestContext, executor);
             vertxRequest.setInputStream(is);
             try {
                 ResteasyContext.pushContext(SecurityContext.class, new QuarkusResteasySecurityContext(request, routingContext));