Done: https://issues.jboss.org/browse/UNDERTOW-710

On Thu, May 12, 2016 at 5:21 AM Stuart Douglas <sdouglas@redhat.com> wrote:
This sounds like a bug, can you file a JIRA? I am traveling at the
moment but I will investigate when I get back.

Stuart

On Wed, May 11, 2016 at 10:54 AM, Oliver Dain <oliver@analyticspot.com> wrote:
> I've got a case where I can call receiveFullBytes but neither the success
> nor the error handler is ever called. My code looks like this:
>
> public static CompletableFuture<ByteSource>
> getCompleteBody(HttpServerExchange exchange) {
>   log.debug("In getCompleteBody.");
>   CompletableFuture<ByteSource> finalResult = new CompletableFuture<>();
>   try {
>     log.debug("Calling receiveFullBytes.");
>     exchange.getRequestReceiver().receiveFullBytes(
>         // Success case.
>         (HttpServerExchange excng, byte[] bytes) -> {
>           log.debug("getFullBytes completed with success.");
>           finalResult.complete(ByteSource.wrap(bytes));
>         },
>
>         // Error case
>         (HttpServerExchange exchng, IOException t) -> {
>           log.warn("getFullBytes completed with an error:", t);
>           finalResult.completeExceptionally(t);
>         }
>     );
>   } catch (Throwable t) {
>     log.warn("receiveFullBytes threw an exception:", t);
>     finalResult.completeExceptionally(t);
>   }
>
>   return finalResult;
> }
>
> I've got a unit test that opens a socket, starts sending data, and then,
> intentionally throws an exception. The test then ensures that the
> CompletableFuture above completes with an exception. Except, it never
> completes.. the test just hangs forever. You can see that the
> "log.debug("Calling receiveFullBytes.")" line does get called and that the
> neither of the log lines in either callback is ever called. The full test
> looks like this:
>
> @Test
> public void getCompleteBodyCompletesWithExceptionOnBodyFailure() throws
> Exception {
>   AtomicBoolean futureRedeemedWithError = new AtomicBoolean(false);
>   CountDownLatch waitForInputToFail = new CountDownLatch(1);
>
>   HttpHandler handler = new HttpHandler() {
>     @Override
>     public void handleRequest(HttpServerExchange exchange) throws Exception
> {
>       log.info("Handler called.");
>       exchange.dispatch();
>       log.info("Calling getCompleteBody");
>       UndertowUtils.getCompleteBody(exchange).exceptionally((Throwable t) ->
> {
>         log.debug("As expected, received an exception:", t);
>         futureRedeemedWithError.set(true);
>         waitForInputToFail.countDown();
>         return null;
>       });
>     }
>   };
>   UndertowTestUtils.RunningServer server =
> UndertowTestUtils.startUndertowOnFreePort(handler);
>
>   // A Body() implementation that will return a few chunks of data but the
> fail
>   Body failingRequestBody = new Body() {
>     private AtomicInteger readCalls = new AtomicInteger(0);
>     @Override
>     public long getContentLength() {
>       return 1000;
>     }
>
>     @Override
>     public long read(ByteBuffer buffer) throws IOException {
>       if (readCalls.getAndIncrement() < 2) {
>         byte[] toSend = "some data".getBytes(Charsets.UTF_8);
>         buffer.put(toSend);
>         return toSend.length;
>       } else {
>         throw new RuntimeException("Fake error on sending data.");
>       }
>     }
>
>     @Override
>     public void close() throws IOException {
>     }
>   };
>
>   // A body generator using the above, busted Body.
>   BodyGenerator failingBodyGenerator = new BodyGenerator() {
>     @Override
>     public Body createBody() throws IOException {
>       return failingRequestBody;
>     }
>   };
>
>   // This will start sending data so our handler gets invoked but it will
> then fail partway through.
>   SimpleAsyncHttpClient client = new SimpleAsyncHttpClient.Builder()
>       .setUrl(String.format("http://localhost:%s", server.getPort()))
>       .build();
>
>   client.post(failingBodyGenerator);
>
>
>   // Test hangs here forever
>   waitForInputToFail.await();
>
>   assertThat(futureRedeemedWithError.get()).isTrue();
> }
>
>
> This feels like a bug. I'd expect the contract of "receiveFullBytes" to be
> that either the success or failure handler gets called exactly once. Is this
> a bug? If not, what am I doing wrong?
>
> Thanks,
>
> Oliver
>
> --
> CTO, Analytic Spot
> 44 West Broadway #222
> Eugene, OR 97401
> analyticspot.com • 425-296-6556
> www.linkedin.com/in/oliverdain
>
> _______________________________________________
> undertow-dev mailing list
> undertow-dev@lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/undertow-dev
--
CTO, Analytic Spot
44 West Broadway #222
Eugene, OR 97401
analyticspot.com • 425-296-6556
www.linkedin.com/in/oliverdain