Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot invoke "org.eclipse.jetty.client.transport.HttpExchange.getRequest()" because "exchange" is null #11841

Closed
garydgregory opened this issue May 24, 2024 · 25 comments · Fixed by #12113
Assignees
Labels
Bug For general bugs on Jetty side High Priority Sponsored This issue affects a user with a commercial support agreement

Comments

@garydgregory
Copy link
Contributor

garydgregory commented May 24, 2024

Jetty version(s)
12.0.9

Jetty Environment
ee9

Java

openjdk version "17.0.11" 2024-04-16
OpenJDK Runtime Environment Temurin-17.0.11+9 (build 17.0.11+9)
OpenJDK 64-Bit Server VM Temurin-17.0.11+9 (build 17.0.11+9, mixed mode, sharing)

Maven

Apache Maven 3.9.6 (bc0240f3c744dd6b6ec2920b3cd08dcc295161ae)
Maven home: C:\java\apache-maven-3.9.6
Java version: 17.0.11, vendor: Eclipse Adoptium, runtime: C:\Program Files\Eclipse Adoptium\jdk-17.0.11.9-hotspot
Default locale: en_US, platform encoding: Cp1252
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"

OS type/version

Microsoft Windows [Version 10.0.19045.4291]

Description

java.lang.NullPointerException: Cannot invoke "org.eclipse.jetty.client.transport.HttpExchange.getRequest()" because "exchange" is null
	at org.eclipse.jetty.client.transport.HttpSender.abortRequest(HttpSender.java:237)
	at org.eclipse.jetty.client.transport.HttpSender.internalAbort(HttpSender.java:389)
	at org.eclipse.jetty.client.transport.HttpSender$ContentSender.onCompleteFailure(HttpSender.java:605)
	at org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:335)
	at org.eclipse.jetty.util.IteratingCallback.iterate(IteratingCallback.java:231)
	at org.eclipse.jetty.client.transport.HttpSender.send(HttpSender.java:85)
	at org.eclipse.jetty.client.transport.internal.HttpChannelOverHTTP.send(HttpChannelOverHTTP.java:86)
	at org.eclipse.jetty.client.transport.HttpChannel.send(HttpChannel.java:142)
	at org.eclipse.jetty.client.transport.HttpConnection.send(HttpConnection.java:112)
	at org.eclipse.jetty.client.transport.internal.HttpConnectionOverHTTP$Delegate.send(HttpConnectionOverHTTP.java:330)
	at org.eclipse.jetty.client.transport.internal.HttpConnectionOverHTTP.send(HttpConnectionOverHTTP.java:159)
	at org.eclipse.jetty.client.transport.HttpDestination.send(HttpDestination.java:444)
	at org.eclipse.jetty.client.transport.HttpDestination.process(HttpDestination.java:420)
	at org.eclipse.jetty.client.transport.HttpDestination.process(HttpDestination.java:375)
	at org.eclipse.jetty.client.transport.HttpDestination.send(HttpDestination.java:358)
	at org.eclipse.jetty.client.transport.HttpDestination.send(HttpDestination.java:352)
	at org.eclipse.jetty.client.transport.HttpDestination.send(HttpDestination.java:329)
	at org.eclipse.jetty.client.transport.HttpDestination.send(HttpDestination.java:308)
	at org.eclipse.jetty.client.transport.HttpRequest.sendAsync(HttpRequest.java:751)
	at org.eclipse.jetty.client.transport.HttpDestination.send(HttpDestination.java:303)
	at org.eclipse.jetty.client.transport.HttpRequest.send(HttpRequest.java:744)
	at org.eclipse.jetty.client.CompletableResponseListener.send(CompletableResponseListener.java:79)
	at org.eclipse.jetty.client.transport.HttpRequest.send(HttpRequest.java:707)
	at _unit test stack frame_
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at _test stack frame_

Perhaps, coincidentally, I just saw a similar stack trace with an another test; note that our custom servlet subclasses Jetty's AsyncMiddleManServlet, so I am not sure if the stack traces below are from the client side since the test uses the Jetty client or the server side since the AsyncMiddleManServlet also uses the Jetty client.

2024-05-24 15:39:45,009 WARN  [HttpClient@3c1e23ff-24][o.e.j.i.SelectorManager] Exception while notifying connection HttpConnectionOverHTTP@7de18c7::SocketChannelEndPoint@3e19ce4[{l=/127.0.0.1:62969,r=localhost/127.0.0.1:59815,OPEN,fill=FI,flush=-,to=0/30000}{io=1/1,kio=1,kro=1}]->[HttpConnectionOverHTTP@7de18c7(l:/127.0.0.1:62969 <-> r:localhost/127.0.0.1:59815,closed=false)=>HttpChannelOverHTTP@46e312fc(exchange=HttpExchange@e8e3{req=HttpRequest[PATCH /api/abc00.txt HTTP/1.1]@77efd004[TERMINATED/null] res=HttpResponse[HTTP/1.1 100 Continue]@78e674a1[PENDING/null]})[send=HttpSenderOverHTTP@26ccedb3(req=FAILURE,failure=java.lang.NullPointerException: Cannot invoke "org.eclipse.jetty.client.transport.HttpExchange.getRequest()" because "this.exchange" is null)[HttpGenerator@218c4e79{s=START}],recv=HttpReceiverOverHTTP@286ac5bc(ex=HttpExchange@e8e3{req=HttpRequest[PATCH /api/abc00.txt HTTP/1.1]@77efd004[TERMINATED/null] res=HttpResponse[HTTP/1.1 100 Continue]@78e674a1[PENDING/null]},rsp=IDLE,failure=null)[HttpParser{s=START,0 of -1}]]]
java.lang.NullPointerException: Cannot invoke "org.eclipse.jetty.client.transport.HttpExchange.getRequest()" because "exchange" is null
	at org.eclipse.jetty.client.transport.HttpSender.abortRequest(HttpSender.java:237) ~[jetty-client-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.client.transport.HttpSender.internalAbort(HttpSender.java:389) ~[jetty-client-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.client.transport.HttpSender$ContentSender.onCompleteFailure(HttpSender.java:605) ~[jetty-client-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:335) ~[jetty-util-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.util.IteratingCallback.iterate(IteratingCallback.java:231) ~[jetty-util-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.client.transport.HttpSender.send(HttpSender.java:85) ~[jetty-client-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.client.transport.internal.HttpChannelOverHTTP.send(HttpChannelOverHTTP.java:86) ~[jetty-client-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.client.transport.HttpChannel.send(HttpChannel.java:142) ~[jetty-client-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.client.transport.HttpConnection.send(HttpConnection.java:112) ~[jetty-client-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.client.transport.internal.HttpConnectionOverHTTP$Delegate.send(HttpConnectionOverHTTP.java:330) ~[jetty-client-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.client.transport.internal.HttpConnectionOverHTTP.send(HttpConnectionOverHTTP.java:159) ~[jetty-client-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.client.transport.HttpDestination.send(HttpDestination.java:444) ~[jetty-client-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.client.transport.HttpDestination.process(HttpDestination.java:420) ~[jetty-client-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.client.transport.HttpDestination.process(HttpDestination.java:375) ~[jetty-client-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.client.transport.HttpDestination.send(HttpDestination.java:358) ~[jetty-client-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.client.transport.HttpDestination.succeeded(HttpDestination.java:291) ~[jetty-client-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.client.AbstractConnectionPool.proceed(AbstractConnectionPool.java:315) ~[jetty-client-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.client.AbstractConnectionPool$FutureConnection.succeeded(AbstractConnectionPool.java:615) ~[jetty-client-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.client.AbstractConnectionPool$FutureConnection.succeeded(AbstractConnectionPool.java:593) ~[jetty-client-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.util.Promise$Wrapper.succeeded(Promise.java:195) ~[jetty-util-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.client.transport.internal.HttpConnectionOverHTTP.onOpen(HttpConnectionOverHTTP.java:167) ~[jetty-client-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.io.SelectorManager.connectionOpened(SelectorManager.java:325) [jetty-io-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.io.ClientConnector$ClientSelectorManager.connectionOpened(ClientConnector.java:616) [jetty-io-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.io.ManagedSelector.createEndPoint(ManagedSelector.java:401) [jetty-io-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.io.ManagedSelector$CreateEndPoint.run(ManagedSelector.java:1056) [jetty-io-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:979) [jetty-util-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1209) [jetty-util-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1164) [jetty-util-12.0.9.jar:12.0.9]
	at java.base/java.lang.Thread.run(Thread.java:840) [?:?]
2024-05-24 15:39:45,027 WARN  [HttpClient@3c1e23ff-18][o.e.j.i.SelectorManager] Exception while notifying connection HttpConnectionOverHTTP@29cf8d83::SocketChannelEndPoint@2d3f260[{l=/[0:0:0:0:0:0:0:1]:62970,r=localhost/[0:0:0:0:0:0:0:1]:59815,OPEN,fill=FI,flush=-,to=2/30000}{io=1/1,kio=1,kro=8}]->[HttpConnectionOverHTTP@29cf8d83(l:/[0:0:0:0:0:0:0:1]:62970 <-> r:localhost/[0:0:0:0:0:0:0:1]:59815,closed=false)=>HttpChannelOverHTTP@565aa3bb(exchange=null)[send=HttpSenderOverHTTP@149f6dee(req=QUEUED,failure=null)[HttpGenerator@41e9496b{s=START}],recv=HttpReceiverOverHTTP@5cb4f3c4(ex=null,rsp=IDLE,failure=null)[HttpParser{s=START,0 of -1}]]]
java.lang.IllegalStateException: Entry already enabled ConcurrentEntry@701b6587{terminated=false,multiplex=0,pooled=HttpConnectionOverHTTP@7de18c7::SocketChannelEndPoint@3e19ce4[{l=/127.0.0.1:62969,r=localhost/127.0.0.1:59815,OPEN,fill=FI,flush=-,to=1/30000}{io=1/1,kio=1,kro=1}]->[HttpConnectionOverHTTP@7de18c7(l:/127.0.0.1:62969 <-> r:localhost/127.0.0.1:59815,closed=false)=>HttpChannelOverHTTP@46e312fc(exchange=null)[send=HttpSenderOverHTTP@26ccedb3(req=FAILURE,failure=java.lang.NullPointerException: Cannot invoke "org.eclipse.jetty.client.transport.HttpExchange.getRequest()" because "this.exchange" is null)[HttpGenerator@218c4e79{s=START}],recv=HttpReceiverOverHTTP@286ac5bc(ex=null,rsp=IDLE,failure=null)[HttpParser{s=START,0 of -1}]]]} for ConcurrentPool@1bf9f49d[strategy=FIRST,inUse=0,size=1,max=64,leaked=0,terminated=false]
	at org.eclipse.jetty.util.ConcurrentPool$ConcurrentEntry.enable(ConcurrentPool.java:489) ~[jetty-util-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.client.AbstractConnectionPool$FutureConnection.succeeded(AbstractConnectionPool.java:612) ~[jetty-client-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.client.AbstractConnectionPool$FutureConnection.succeeded(AbstractConnectionPool.java:593) ~[jetty-client-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.util.Promise$Wrapper.succeeded(Promise.java:195) ~[jetty-util-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.client.transport.internal.HttpConnectionOverHTTP.onOpen(HttpConnectionOverHTTP.java:167) ~[jetty-client-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.io.SelectorManager.connectionOpened(SelectorManager.java:325) [jetty-io-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.io.ClientConnector$ClientSelectorManager.connectionOpened(ClientConnector.java:616) [jetty-io-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.io.ManagedSelector.createEndPoint(ManagedSelector.java:401) [jetty-io-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.io.ManagedSelector$CreateEndPoint.run(ManagedSelector.java:1056) [jetty-io-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:979) [jetty-util-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1209) [jetty-util-12.0.9.jar:12.0.9]
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1164) [jetty-util-12.0.9.jar:12.0.9]
	at java.base/java.lang.Thread.run(Thread.java:840) [?:?]

Note that the test hangs, perhaps due to the second stack trace in the block above.

How to reproduce?

The reproducer is in PR: #11891, but it is "random", sometimes it happens, sometimes is does not. Using Microsoft's SysInternal's CPU Stres tool helps recreate the issue.

This stack trace is from a test case using a Jetty 12 HTTP Client to a Jetty 12 Server using a custom AsyncMiddleManServlet subclass. I can't share any of it unfortunately.

I am wondering if it is possible that there is some asynchronous bad luck involved here.

@garydgregory garydgregory added the Bug For general bugs on Jetty side label May 24, 2024
@garydgregory
Copy link
Contributor Author

Here is a PR: #11891

@sbordet
Copy link
Contributor

sbordet commented Jun 10, 2024

@garydgregory I'm looking at this, and I think there is something else going on, and the NPE appears to be a red herring.

I'll keep the issue posted.

@garydgregory
Copy link
Contributor Author

garydgregory commented Jun 10, 2024

@sbordet
The NPE in this issue and the problems in #11894 are in the way to reproduce another more difficult to reproduce issue on the server-side which shows up as an HTTP 502 Bad Gateway in the test below.

java.lang.IllegalStateException: demand pending
	at org.eclipse.jetty.io/org.eclipse.jetty.io.content.AsyncContent.demand(AsyncContent.java:222)

(full stack below)
In addition to "fixing" the NPEs with my PR and to workaround the Jetty client hanging problem, I am using (like our actual test suite), Apache HttpClient 5 as the HTTP client, instead of the Jetty Client in a AsyncMiddleManServletTest test:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import jakarta.servlet.ServletException;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.routing.DefaultProxyRoutePlanner;
import org.apache.hc.client5.http.routing.HttpRoutePlanner;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.support.ClassicRequestBuilder;
import org.apache.hc.core5.util.Timeout;
import org.eclipse.jetty.client.AsyncRequestContent;
import org.eclipse.jetty.client.BytesRequestContent;
import org.eclipse.jetty.client.CompletableResponseListener;
import org.eclipse.jetty.client.ContentResponse;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.HttpProxy;
import org.eclipse.jetty.client.Request;
import org.eclipse.jetty.client.Response;
import org.eclipse.jetty.ee9.servlet.ServletContextHandler;
import org.eclipse.jetty.ee9.servlet.ServletHolder;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpHeaderValue;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.RuntimeIOException;
import org.eclipse.jetty.logging.StacklessLogging;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.Utf8StringBuilder;
import org.eclipse.jetty.util.ajax.JSON;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.OS;
import org.junit.jupiter.api.extension.ExtendWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

// This is in AsyncMiddleManServletTest ...

    @Test
    public void testServletExpect100ApacheHttpClient5() throws Exception
    {
        startServer(new HttpServlet()
        {
            private AtomicInteger count = new AtomicInteger();

            @Override
            protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException
            {
                // Adding logging may slow things down enough to not hang
                // System.out.printf("Origin servicing %d%n", count.incrementAndGet());
                // Send the 100 Continue.
                ServletInputStream input = request.getInputStream();
                // Echo the content.
                IO.copy(input, response.getOutputStream());
                // Slowing down the origin allows the test to not hang sometimes
//                try {
//                    Thread.sleep(50);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
            }
        });
        startProxy(new AsyncMiddleManServlet()
        {
            protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
            {
                // Adding logging may slow things down enough to not hang
                // System.out.printf("AsyncMiddleManServlet servicing %n");
                super.service(request, response);
            }
        });

        RequestConfig requestConfig = RequestConfig.custom()
                .setExpectContinueEnabled(true)
                .setResponseTimeout(5, TimeUnit.SECONDS)
                .build();
        HttpHost proxyHost = new HttpHost("localhost", proxyConnector.getLocalPort());
        HttpHost targetHost = new HttpHost("localhost", serverConnector.getLocalPort());
        HttpRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxyHost);
        try (CloseableHttpClient httpclient = HttpClients.custom()
                .setDefaultRequestConfig(requestConfig)
                .setRoutePlanner(routePlanner)
                .build()) {
            // loop to attempt increase odds of hanging
            for (int i = 1; i <= 500; i++) {
                long start = System.currentTimeMillis();
                System.out.printf("Sending #%d%n", i);
                ClassicHttpRequest request = ClassicRequestBuilder.post("http://localhost:" + serverConnector.getLocalPort())
                        .setHeader(HttpHeader.EXPECT.toString(), HttpHeaderValue.CONTINUE.toString())
                        .setEntity("a")
                        .build();
                httpclient.execute(targetHost, request, response -> {
                    System.out.println(response.getCode() + " " + response.getReasonPhrase());
                    assertEquals(200, response.getCode());
                    HttpEntity entity = response.getEntity();
                    EntityUtils.consume(entity);
                    return null;
                });
                System.out.printf(" %,d ms%n", System.currentTimeMillis() - start);
            }
        }
    }

Randomly produces (you might have to try a few times and/or stress the CPU):

java.lang.IllegalStateException: demand pending
	at org.eclipse.jetty.io/org.eclipse.jetty.io.content.AsyncContent.demand(AsyncContent.java:222)
	at org.eclipse.jetty.client/org.eclipse.jetty.client.transport.HttpSender$ContentSender.process(HttpSender.java:525)
	at org.eclipse.jetty.util/org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:250)
	at org.eclipse.jetty.util/org.eclipse.jetty.util.IteratingCallback.iterate(IteratingCallback.java:231)
	at org.eclipse.jetty.client/org.eclipse.jetty.client.transport.HttpSender.send(HttpSender.java:85)
	at org.eclipse.jetty.client/org.eclipse.jetty.client.transport.internal.HttpChannelOverHTTP.send(HttpChannelOverHTTP.java:86)
	at org.eclipse.jetty.client/org.eclipse.jetty.client.transport.HttpChannel.send(HttpChannel.java:142)
	at org.eclipse.jetty.client/org.eclipse.jetty.client.transport.HttpConnection.send(HttpConnection.java:112)
	at org.eclipse.jetty.client/org.eclipse.jetty.client.transport.internal.HttpConnectionOverHTTP$Delegate.send(HttpConnectionOverHTTP.java:330)
	at org.eclipse.jetty.client/org.eclipse.jetty.client.transport.internal.HttpConnectionOverHTTP.send(HttpConnectionOverHTTP.java:159)
	at org.eclipse.jetty.client/org.eclipse.jetty.client.transport.HttpDestination.send(HttpDestination.java:444)
	at org.eclipse.jetty.client/org.eclipse.jetty.client.transport.HttpDestination.process(HttpDestination.java:420)
	at org.eclipse.jetty.client/org.eclipse.jetty.client.transport.HttpDestination.process(HttpDestination.java:375)
	at org.eclipse.jetty.client/org.eclipse.jetty.client.transport.HttpDestination.send(HttpDestination.java:358)
	at org.eclipse.jetty.client/org.eclipse.jetty.client.transport.HttpDestination.send(HttpDestination.java:352)
	at org.eclipse.jetty.client/org.eclipse.jetty.client.transport.HttpDestination.send(HttpDestination.java:329)
	at org.eclipse.jetty.client/org.eclipse.jetty.client.transport.HttpDestination.send(HttpDestination.java:308)
	at org.eclipse.jetty.client/org.eclipse.jetty.client.transport.HttpRequest.sendAsync(HttpRequest.java:751)
	at org.eclipse.jetty.client/org.eclipse.jetty.client.transport.HttpDestination.send(HttpDestination.java:303)
	at org.eclipse.jetty.client/org.eclipse.jetty.client.transport.HttpRequest.send(HttpRequest.java:744)
	at org.eclipse.jetty.ee9.proxy/org.eclipse.jetty.ee9.proxy.AbstractProxyServlet.sendProxyRequest(AbstractProxyServlet.java:637)
	at org.eclipse.jetty.ee9.proxy/org.eclipse.jetty.ee9.proxy.AsyncMiddleManServlet.service(AsyncMiddleManServlet.java:128)
	at org.eclipse.jetty.ee9.proxy/org.eclipse.jetty.ee9.proxy.AsyncMiddleManServletTest$5.service(AsyncMiddleManServletTest.java:447)
	at jetty.servlet.api@5.0.2/jakarta.servlet.http.HttpServlet.service(HttpServlet.java:587)
	at org.eclipse.jetty.ee9.servlet.ServletHolder.handle(ServletHolder.java:765)
	at org.eclipse.jetty.ee9.servlet.ServletHandler.doHandle(ServletHandler.java:528)
	at org.eclipse.jetty.ee9.nested.ScopedHandler.nextHandle(ScopedHandler.java:195)
	at org.eclipse.jetty.ee9.nested.SessionHandler.doHandle(SessionHandler.java:476)
	at org.eclipse.jetty.ee9.nested.ScopedHandler.nextHandle(ScopedHandler.java:195)
	at org.eclipse.jetty.ee9.nested.ContextHandler.doHandle(ContextHandler.java:1034)
	at org.eclipse.jetty.ee9.nested.ScopedHandler.nextScope(ScopedHandler.java:164)
	at org.eclipse.jetty.ee9.servlet.ServletHandler.doScope(ServletHandler.java:483)
	at org.eclipse.jetty.ee9.nested.ScopedHandler.nextScope(ScopedHandler.java:162)
	at org.eclipse.jetty.ee9.nested.SessionHandler.doScope(SessionHandler.java:470)
	at org.eclipse.jetty.ee9.nested.ScopedHandler.nextScope(ScopedHandler.java:162)
	at org.eclipse.jetty.ee9.nested.ContextHandler.doScope(ContextHandler.java:955)
	at org.eclipse.jetty.ee9.nested.ScopedHandler.handle(ScopedHandler.java:125)
	at org.eclipse.jetty.ee9.nested.ContextHandler.handle(ContextHandler.java:1693)
	at org.eclipse.jetty.ee9.nested.HttpChannel$RequestDispatchable.dispatch(HttpChannel.java:1575)
	at org.eclipse.jetty.ee9.nested.HttpChannel.dispatch(HttpChannel.java:737)
	at org.eclipse.jetty.ee9.nested.HttpChannel.handle(HttpChannel.java:510)
	at org.eclipse.jetty.ee9.nested.ContextHandler$CoreContextHandler$CoreToNestedHandler.handle(ContextHandler.java:2727)
	at org.eclipse.jetty.server/org.eclipse.jetty.server.handler.ContextHandler.handle(ContextHandler.java:851)
	at org.eclipse.jetty.server/org.eclipse.jetty.server.Server.handle(Server.java:181)
	at org.eclipse.jetty.server/org.eclipse.jetty.server.internal.HttpChannelState$HandlerInvoker.run(HttpChannelState.java:635)
	at org.eclipse.jetty.server/org.eclipse.jetty.server.internal.HttpConnection.onFillable(HttpConnection.java:403)
	at org.eclipse.jetty.io/org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:322)
	at org.eclipse.jetty.io/org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:99)
	at org.eclipse.jetty.io/org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)
	at org.eclipse.jetty.util/org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.runTask(AdaptiveExecutionStrategy.java:478)
	at org.eclipse.jetty.util/org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.consumeTask(AdaptiveExecutionStrategy.java:441)
	at org.eclipse.jetty.util/org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.tryProduce(AdaptiveExecutionStrategy.java:293)
	at org.eclipse.jetty.util/org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.run(AdaptiveExecutionStrategy.java:201)
	at org.eclipse.jetty.util/org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:311)
	at org.eclipse.jetty.util/org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:979)
	at org.eclipse.jetty.util/org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1209)
	at org.eclipse.jetty.util/org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1164)
	at java.base/java.lang.Thread.run(Thread.java:840)

The most simple way to see this stack trace is to add a call to printStackTrace() call in AbstractProxyServlet.proxyResponseStatus(Throwable) like this:

    protected int proxyResponseStatus(Throwable failure)
    {
        failure.printStackTrace();
        return failure instanceof TimeoutException
            ? HttpStatus.GATEWAY_TIMEOUT_504
            : HttpStatus.BAD_GATEWAY_502;
    }

Using logging can affect the timing and randomness too much to easily reproduce this.

@sbordet
Copy link
Contributor

sbordet commented Jun 12, 2024

@garydgregory we can reproduce both exceptions (NPE and demand pending), but still working on a better solution that would avoid both, rather than guarding against.

@garydgregory
Copy link
Contributor Author

@sbordet Thank you for the update. Looking forward to a solution 😄

@sbordet
Copy link
Contributor

sbordet commented Jun 17, 2024

@garydgregory how sure you are that you are not sending a request with 100-Continue, but Content-Length: 0?

Because I can reproduce the issue with that combination, but as soon as there is a content, it's not reproducible.

We should support that combination, I think, but it's technically not necessary to send expect 100-Continue if there is no content.

@garydgregory
Copy link
Contributor Author

garydgregory commented Jun 17, 2024

Hello @sbordet,

Yes, it is reproducible with and without an HTTP body.

Note that the randomly failing test above uses an HTTP POST with a one-character body.

This showcases the observation that the shorter the body, the easier it might be to reproduce. Reproducing the issue more reliably may require using a CPU stress program like Micorsoft SysInternal’s “CPU Stres” (Windows) app. That’s the case on my laptop: ThinkPad L15; Windows 10 (22H2 build 19045.4412); CPU 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz 2.80 GHz; 16 GB RAM.

I agree with your statement that an expect 100 is not needed if there is no body but unfortunately that’s not what we have to support in the real world with actual client apps.

Some of our testing and actual usage reflects what we've seen HTTP clients send our server in the wild. We have instances where the HTTP framework used on the client side which we do not control, enables expect 100, whether it's needed or not. We must deal with it, which means for us that Jetty should allow it without throwing NPEs or “demand pending” exception (albeit random but reproducible).

To recap, there are several issues at play that are likely related, three exceptions: The two NPEs and the “demand pending” exceptions, plus the Jetty client hanging.

Gathering links for record keeping:

TY!

@garydgregory
Copy link
Contributor Author

Hello @sbordet
Is there anything more I can do to help move solutions (partial, proposed or otherwise) forward?

@lorban
Copy link
Contributor

lorban commented Jun 24, 2024

@garydgregory thanks for the offer, but unfortunately I don't see much you could do to help speeding up the resolution of this bug.

The team is a bit stretched thin at the moment so it's hard to find cycles, but I promise we haven't forgotten about you and will get this fixed ASAP. I'm sorry about having to make you wait.

@garydgregory
Copy link
Contributor Author

@sbordet Thank you for the update! 😄

Randgalt added a commit to trinodb/aws-proxy that referenced this issue Jul 22, 2024
jetty/jetty.project#11841 has an NPE
when using 100-Continue. This hack is a workaround.

- Create a new module that generates a JAR that will sort first in
the classpath
- Put a hacked version of Jetty's `HttpSender` in this module that
has a fix
- The Java classloader will load this version of the class first,
thus working around the problem

This hack should be removed as soon as possible
Randgalt added a commit to trinodb/aws-proxy that referenced this issue Jul 22, 2024
jetty/jetty.project#11841 has an NPE
when using 100-Continue. This hack is a workaround.

- Create a new module that generates a JAR that will sort first in
the classpath
- Put a hacked version of Jetty's `HttpSender` in this module that
has a fix
- The Java classloader will load this version of the class first,
thus working around the problem

This hack should be removed as soon as possible
Randgalt added a commit to trinodb/aws-proxy that referenced this issue Jul 22, 2024
jetty/jetty.project#11841 has an NPE
when using 100-Continue. This hack is a workaround.

- Create a new module that generates a JAR that will sort first in
the classpath
- Put a hacked version of Jetty's `HttpSender` in this module that
has a fix
- The Java classloader will load this version of the class first,
thus working around the problem

This hack should be removed as soon as possible
@lorban lorban added Sponsored This issue affects a user with a commercial support agreement Medium Priority Needs attention soon, but is not the highest priority labels Jul 23, 2024
@lorban lorban self-assigned this Jul 23, 2024
Randgalt added a commit to trinodb/aws-proxy that referenced this issue Jul 24, 2024
jetty/jetty.project#11841 has an NPE
when using 100-Continue. This hack is a workaround.

- Create a new module that generates a JAR that will sort first in
the classpath
- Put a hacked version of Jetty's `HttpSender` in this module that
has a fix
- The Java classloader will load this version of the class first,
thus working around the problem

This hack should be removed as soon as possible
Randgalt added a commit to trinodb/aws-proxy that referenced this issue Jul 24, 2024
jetty/jetty.project#11841 has an NPE
when using 100-Continue. This hack is a workaround.

- Create a new module that generates a JAR that will sort first in
the classpath
- Put a hacked version of Jetty's `HttpSender` in this module that
has a fix
- The Java classloader will load this version of the class first,
thus working around the problem

This hack should be removed as soon as possible
Randgalt added a commit to trinodb/aws-proxy that referenced this issue Jul 24, 2024
jetty/jetty.project#11841 has an NPE
when using 100-Continue. This hack is a workaround.

- Create a new module that generates a JAR that will sort first in
the classpath
- Put a hacked version of Jetty's `HttpSender` in this module that
has a fix
- The Java classloader will load this version of the class first,
thus working around the problem

This hack should be removed as soon as possible
Randgalt added a commit to trinodb/aws-proxy that referenced this issue Jul 24, 2024
jetty/jetty.project#11841 has an NPE
when using 100-Continue. This hack is a workaround.

- Create a new module that generates a JAR that will sort first in
the classpath
- Put a hacked version of Jetty's `HttpSender` in this module that
has a fix
- The Java classloader will load this version of the class first,
thus working around the problem

This hack should be removed as soon as possible
@joakime joakime added High Priority and removed Medium Priority Needs attention soon, but is not the highest priority labels Jul 24, 2024
@sbordet
Copy link
Contributor

sbordet commented Jul 31, 2024

@garydgregory sorry it took so long, but there were multiple issues, and it took a while to get a grip on all of them.

Can you please try branch fix/jetty-12.0.x/httpsender-proxy-continue-fixes and see if it works for you?

@sbordet sbordet linked a pull request Jul 31, 2024 that will close this issue
@garydgregory
Copy link
Contributor Author

Thank you @sbordet I will test...

@garydgregory
Copy link
Contributor Author

garydgregory commented Aug 2, 2024

Hello @sbordet

I built and installed (mvn clean install -DskipTests) the branch locally and it does fix the issue 👍 Than you.

Two items of note:

  • It looks like using the Jetty HTTP Client for a GET without a body, a Content-Length and a Content-Type header is now sent, which was not a case in 11.x and causes some of our tests to fail (because we record most HTTP data and assert it):
Accept-Encoding: gzip
User-Agent: Jetty/12.0.13-SNAPSHOT
Host: localhost:50650
Content-Type: application/octet-stream
Content-Length: 0

This is different from the other HTTP clients we test and a difference in behavior from 11.x we'd need to adapt unless it is a mistake. Please let me know.

  • It was easy for me to adapt but it should be noted in the release notes that there is a binary incompatible change:
    org.eclipse.jetty.ee9.proxy.AsyncMiddleManServlet.onContinue(HttpServletRequest, Request) returns a Runnable in the branch but is a void method in 12.0.12

Well done & thank you!

@sbordet
Copy link
Contributor

sbordet commented Aug 2, 2024

@garydgregory thanks for the feedback!

The first bullet should be addressed by 4e9755d, so perhaps you can update to the latest branch code and try again?

The second bullet was necessary, but that method should not be overridden or called by applications.
Are you overriding it? If so, may I ask why?

@garydgregory
Copy link
Contributor Author

garydgregory commented Aug 2, 2024

@sbordet

Thank you for the update, I'll pull, build, and test next.

WRT to the onContinue() override, it seems to be no longer needed. In previous versions, we did see random runs where the implementation in AsyncMiddleManServlet called proxyRequest.getAttributes().get(CONTINUE_ACTION_ATTRIBUTE) which returned null and caused an NPE in onContinue(). The current implementation of AsyncMiddleMan seems to make this no longer possible, I hope.

@garydgregory
Copy link
Contributor Author

Hello @sbordet
The news is mostly good! I only have 9 test failing tests that I am debugging ATM. This is all the same test parameterized with different inputs (HTTP method DELETE, GET, PATCH fail but PUT and POST are OK, different HTTP clients: Apache HttpComponents 4.x, 5.x, and Jetty Client). I'll post back here ASAP with details.

@garydgregory
Copy link
Contributor Author

@sbordet

OK, I think we're good with this branch! Thank you!

What are expectations regarding a merge and release? (Do you have a public snapshot Maven repository?)

Details: Our tests made some special allowances for some probably unusual behavior in Jetty 11.0.20 where we saw Jetty return a 417 "Expectation Failed" for DELETE, GET, and PATCH requests without a body but with an Expect 100 header. It's simple enough to update these tests on our end.

@olamy
Copy link
Member

olamy commented Aug 8, 2024

OK, I think we're good with this branch! Thank you!

What are expectations regarding a merge and release? (Do you have a public snapshot Maven repository?)

@garydgregory once merged a nightly build will push snapshot to https://oss.sonatype.org/content/repositories/jetty-snapshots

Details: Our tests made some special allowances for some probably unusual behavior in Jetty 11.0.20 where we saw Jetty return a 417 "Expectation Failed" for DELETE, GET, and PATCH requests without a body but with an Expect 100 header. It's simple enough to update these tests on our end.

@garydgregory
Copy link
Contributor Author

TY @olamy I will test on the next build now that the PR has been merged.

@olamy
Copy link
Member

olamy commented Aug 13, 2024

@garydgregory
Copy link
Contributor Author

Arg, using 12.0.13-SNAPSHOT, I just got a random:

java.lang.NullPointerException: Cannot invoke "org.eclipse.jetty.client.transport.HttpExchange.getRequest()" because "exchange" is null
	at org.eclipse.jetty.client.transport.HttpSender.abortRequest(HttpSender.java:237)
	at org.eclipse.jetty.client.transport.HttpSender.internalAbort(HttpSender.java:392)
	at org.eclipse.jetty.client.transport.HttpSender$ContentSender.onCompleteFailure(HttpSender.java:629)
	at org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:354)
	at org.eclipse.jetty.util.IteratingCallback.iterate(IteratingCallback.java:243)
	at org.eclipse.jetty.client.transport.HttpSender.send(HttpSender.java:85)
	at org.eclipse.jetty.client.transport.internal.HttpChannelOverHTTP.send(HttpChannelOverHTTP.java:86)
	at org.eclipse.jetty.client.transport.HttpChannel.send(HttpChannel.java:142)
	at org.eclipse.jetty.client.transport.HttpConnection.send(HttpConnection.java:112)
	at org.eclipse.jetty.client.transport.internal.HttpConnectionOverHTTP$Delegate.send(HttpConnectionOverHTTP.java:367)
	at org.eclipse.jetty.client.transport.internal.HttpConnectionOverHTTP.send(HttpConnectionOverHTTP.java:162)
	at org.eclipse.jetty.client.transport.HttpDestination.send(HttpDestination.java:444)
	at org.eclipse.jetty.client.transport.HttpDestination.process(HttpDestination.java:420)
	at org.eclipse.jetty.client.transport.HttpDestination.process(HttpDestination.java:375)
	at org.eclipse.jetty.client.transport.HttpDestination.send(HttpDestination.java:358)
	at org.eclipse.jetty.client.transport.HttpDestination.send(HttpDestination.java:352)
	at org.eclipse.jetty.client.transport.HttpDestination.send(HttpDestination.java:329)
	at org.eclipse.jetty.client.transport.HttpDestination.send(HttpDestination.java:308)
	at org.eclipse.jetty.client.transport.HttpRequest.sendAsync(HttpRequest.java:751)
	at org.eclipse.jetty.client.transport.HttpDestination.send(HttpDestination.java:303)
	at org.eclipse.jetty.client.transport.HttpRequest.send(HttpRequest.java:744)
	at org.eclipse.jetty.client.CompletableResponseListener.send(CompletableResponseListener.java:79)
	at org.eclipse.jetty.client.transport.HttpRequest.send(HttpRequest.java:707)
    <custom code redacted>

Any thoughts?

garydgregory added a commit to garydgregory/jetty.project that referenced this issue Aug 30, 2024
@garydgregory
Copy link
Contributor Author

garydgregory commented Aug 30, 2024

@lorban

I've updated the test to show the failure still occurs, always, eventually, for me. I would be curious to see what your testing reveals.

The test is in https://github.com/garydgregory/jetty.project/pull/new/12.0.x_issue_11841_NPE

Run mvn test -pl jetty-ee9/jetty-ee9-proxy -Dtest=AsyncMiddleManServletTest#testServletExpect100ApacheHttpClient5 -Dcheckstyle.skip=true

This test shows the NPEs on the console.

Eventually, it will fail the test which checks for replies with status 200, for example:

...
# 7,142 1 ms
java.lang.NullPointerException: Cannot invoke "org.eclipse.jetty.client.transport.HttpExchange.getRequest()" because "exchange" is null
        at org.eclipse.jetty.client@12.0.13-SNAPSHOT/org.eclipse.jetty.client.transport.HttpSender$ContentSender.process(HttpSender.java:511)
        at org.eclipse.jetty.util@12.0.13-SNAPSHOT/org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:262)
        at org.eclipse.jetty.util@12.0.13-SNAPSHOT/org.eclipse.jetty.util.IteratingCallback.succeeded(IteratingCallback.java:401)
        at org.eclipse.jetty.io@12.0.13-SNAPSHOT/org.eclipse.jetty.io.content.AsyncContent.runDemandCallback(AsyncContent.java:238)
        at org.eclipse.jetty.io@12.0.13-SNAPSHOT/org.eclipse.jetty.io.content.AsyncContent.invokeDemandCallback(AsyncContent.java:231)
        at org.eclipse.jetty.util@12.0.13-SNAPSHOT/org.eclipse.jetty.util.thread.SerializedInvoker$Link.run(SerializedInvoker.java:245)
        at org.eclipse.jetty.util@12.0.13-SNAPSHOT/org.eclipse.jetty.util.thread.SerializedInvoker.run(SerializedInvoker.java:154)
        at org.eclipse.jetty.io@12.0.13-SNAPSHOT/org.eclipse.jetty.io.content.AsyncContent.offer(AsyncContent.java:117)
        at org.eclipse.jetty.io@12.0.13-SNAPSHOT/org.eclipse.jetty.io.content.AsyncContent.close(AsyncContent.java:151)
        at org.eclipse.jetty.ee9.proxy@12.0.13-SNAPSHOT/org.eclipse.jetty.ee9.proxy.AsyncMiddleManServlet$ProxyReader.process(AsyncMiddleManServlet.java:382)
        at org.eclipse.jetty.ee9.proxy@12.0.13-SNAPSHOT/org.eclipse.jetty.ee9.proxy.AsyncMiddleManServlet$ProxyReader.process(AsyncMiddleManServlet.java:328)
        at org.eclipse.jetty.util@12.0.13-SNAPSHOT/org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:262)
        at org.eclipse.jetty.util@12.0.13-SNAPSHOT/org.eclipse.jetty.util.IteratingCallback.iterate(IteratingCallback.java:243)
        at org.eclipse.jetty.ee9.proxy@12.0.13-SNAPSHOT/org.eclipse.jetty.ee9.proxy.AsyncMiddleManServlet$ProxyReader.onDataAvailable(AsyncMiddleManServlet.java:280)
        at org.eclipse.jetty.ee9.nested.HttpInput.run(HttpInput.java:434)
        at org.eclipse.jetty.ee9.nested.ContextHandler.handle(ContextHandler.java:1100)
        at org.eclipse.jetty.ee9.nested.HttpChannel.handle(HttpChannel.java:597)
        at org.eclipse.jetty.ee9.nested.HttpChannel.lambda$needContent$0(HttpChannel.java:161)
        at org.eclipse.jetty.server@12.0.13-SNAPSHOT/org.eclipse.jetty.server.handler.ContextHandler$ScopedContext.run(ContextHandler.java:1507)
        at org.eclipse.jetty.server@12.0.13-SNAPSHOT/org.eclipse.jetty.server.handler.ContextRequest$OnContextDemand.run(ContextRequest.java:74)
        at org.eclipse.jetty.util@12.0.13-SNAPSHOT/org.eclipse.jetty.util.thread.SerializedInvoker$Link.run(SerializedInvoker.java:245)
        at org.eclipse.jetty.server@12.0.13-SNAPSHOT/org.eclipse.jetty.server.internal.HttpConnection$DemandContentCallback.succeeded(HttpConnection.java:680)
        at org.eclipse.jetty.io@12.0.13-SNAPSHOT/org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:99)
        at org.eclipse.jetty.io@12.0.13-SNAPSHOT/org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)
        at org.eclipse.jetty.util@12.0.13-SNAPSHOT/org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.runTask(AdaptiveExecutionStrategy.java:478)
        at org.eclipse.jetty.util@12.0.13-SNAPSHOT/org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.consumeTask(AdaptiveExecutionStrategy.java:441)
        at org.eclipse.jetty.util@12.0.13-SNAPSHOT/org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.tryProduce(AdaptiveExecutionStrategy.java:293)
        at org.eclipse.jetty.util@12.0.13-SNAPSHOT/org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.run(AdaptiveExecutionStrategy.java:201)
        at org.eclipse.jetty.util@12.0.13-SNAPSHOT/org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:311)
        at org.eclipse.jetty.util@12.0.13-SNAPSHOT/org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:979)
        at org.eclipse.jetty.util@12.0.13-SNAPSHOT/org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1209)
        at org.eclipse.jetty.util@12.0.13-SNAPSHOT/org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1164)
        at java.base/java.lang.Thread.run(Thread.java:840)
# 7,143 5 ms
...
# 7,222 1 ms
# 7,223 1 ms
# 7,224 1 ms
# 7,225 0 ms
java.lang.NullPointerException
2024-08-30 18:35:06.420:INFO :oejs.Server:ForkJoinPool-1-worker-1: Stopped oejs.Server@221f8fd5{STOPPING}[12.0.13-SNAPSHOT,sto=0]
2024-08-30 18:35:06.424:INFO :oejs.AbstractConnector:ForkJoinPool-1-worker-1: Stopped ServerConnector@1b89ab2f{HTTP/1.1, (http/1.1)}{0.0.0.0:0}
[ERROR] Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 11.66 s <<< FAILURE! -- in org.eclipse.jetty.ee9.proxy.AsyncMiddleManServletTest
[ERROR] org.eclipse.jetty.ee9.proxy.AsyncMiddleManServletTest.testServletExpect100ApacheHttpClient5 -- Time elapsed: 11.53 s <<< FAILURE!
org.opentest4j.AssertionFailedError: expected: <200> but was: <502>
        at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
        at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
        at org.junit.jupiter.api.AssertEquals.failNotEqual(AssertEquals.java:197)
        at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:150)
        at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:145)
        at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:531)
        at org.eclipse.jetty.ee9.proxy@12.0.13-SNAPSHOT/org.eclipse.jetty.ee9.proxy.AsyncMiddleManServletTest.lambda$testServletExpect100ApacheHttpClient5$0(AsyncMiddleManServletTest.java:260)
        at org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:247)
        at org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:213)
        at org.eclipse.jetty.ee9.proxy@12.0.13-SNAPSHOT/org.eclipse.jetty.ee9.proxy.AsyncMiddleManServletTest.testServletExpect100ApacheHttpClient5(AsyncMiddleManServletTest.java:258)
        at java.base/java.lang.reflect.Method.invoke(Method.java:569)
        at java.base/java.util.concurrent.RecursiveAction.exec(RecursiveAction.java:194)
        at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
        at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
        at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
        at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
        at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)

[INFO]
[INFO] Results:
[INFO]
[ERROR] Failures:
[ERROR]   AsyncMiddleManServletTest.testServletExpect100ApacheHttpClient5:258->lambda$testServletExpect100ApacheHttpClient5$0:260 expected: <200> but was: <502>
[INFO]
[ERROR] Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  39.722 s
[INFO] Finished at: 2024-08-30T18:35:07-04:00
[INFO] ------------------------------------------------------------------------

I am using:

Apache Maven 3.9.9 (8e8579a9e76f7d015ee5ec7bfcdc97d260186937)
Maven home: C:\java\apache-maven-3.9.9
Java version: 17.0.12, vendor: Eclipse Adoptium, runtime: C:\Program Files\Eclipse Adoptium\jdk-17.0.12.7-hotspot
Default locale: en_US, platform encoding: Cp1252
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"

garydgregory added a commit to garydgregory/jetty.project that referenced this issue Aug 30, 2024
@garydgregory
Copy link
Contributor Author

Hello @lorban @sbordet
This is still a problem in 12.0.13. Shouldn't this issue be reopened?

@sbordet
Copy link
Contributor

sbordet commented Sep 12, 2024

@garydgregory we're working on it, @lorban will update this and/or open a new issue.

@lorban
Copy link
Contributor

lorban commented Sep 13, 2024

@garydgregory see #12210 (comment)

lorban added a commit that referenced this issue Sep 18, 2024
Signed-off-by: Ludovic Orban <lorban@bitronix.be>
lorban added a commit that referenced this issue Sep 23, 2024
Signed-off-by: Ludovic Orban <lorban@bitronix.be>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug For general bugs on Jetty side High Priority Sponsored This issue affects a user with a commercial support agreement
Projects
No open projects
Status: ✅ Done
Development

Successfully merging a pull request may close this issue.

5 participants