eclipse-ee4j / eclipse-ee4j/jersey
Deadlock when LoggingFeature with PAYLOAD_ANY is registered on the client with JdkConnectorProvider
- Dominant language
- Java
- Stars
- 730
- Forks
- 382
- PR merge metrics
- No merged PRs in 30d
Description
Hello,
i ran into a hard hang when combining `JdkConnectorProvider` with `LoggingFeature(Verbosity.PAYLOAD_ANY)` on the Jersey client. The client submits an async request but the `Future.get()` never returns — the process hangs indefinitely.
I couldn't find any hint whether this problem is known or not. Am I missing sth?
Thanks in advance
My environment is:
- Jersey: 3.1.9
- Java: 21.0.6 (OpenJDK)
- OS: Windows 11
- Connector: `jersey-jdk-connector`
Steps to reproduce (a threaddump is attached):
[threaddump-1783593915981.tdump.txt](https://github.com/user-attachments/files/29845199/threaddump-1783593915981.tdump.txt)
```java
import com.sun.net.httpserver.HttpServer;
import jakarta.ws.rs.core.Response;
import org.glassfish.jersey.client.JerseyClientBuilder;
import org.glassfish.jersey.jdk.connector.JdkConnectorProvider;
import org.glassfish.jersey.logging.LoggingFeature;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Reproducer {
public static void main(String[] args) throws Exception {
byte[] body = "Hello".getBytes(StandardCharsets.UTF_8);
HttpServer server = HttpServer.create(new InetSocketAddress("localhost", 0), 0);
server.createContext("/test", exchange -> {
exchange.getResponseHeaders().set("Content-Type", "text/plain");
exchange.sendResponseHeaders(200, body.length);
exchange.getResponseBody().write(body);
exchange.getResponseBody().close();
});
server.setExecutor(null);
server.start();
String url = "http://localhost:" + server.getAddress().getPort() + "/test";
var client = (org.glassfish.jersey.client.JerseyClient)
JerseyClientBuilder.newBuilder()
.register(new LoggingFeature(
Logger.getLogger("test"),
Level.INFO,
LoggingFeature.Verbosity.PAYLOAD_ANY,
65535))
.build();
client.getConfiguration().connectorProvider(new JdkConnectorProvider());
System.out.println("Sending request ...");
Future future = client.target(url).request().buildGet().submit();
try {
Response response = future.get(10, TimeUnit.SECONDS);
System.out.println("OK: " + response.readEntity(String.class));
} catch (java.util.concurrent.TimeoutException e) {
System.err.println("DEADLOCK: timed out after 10s.");
}
client.close();
server.stop(0);
}
}
```
The code does not hang when:
- the line `client.getConfiguration().connectorProvider(new JdkConnectorProvider());` is comment out
- instead of `LoggingFeature.Verbosity.PAYLOAD_ANY` the value `LoggingFeature.Verbosity.HEADERS_ONLY` is used
Best Regards,
Contributor guide
Research direction
Start by running the supplied Java reproducer with JdkConnectorProvider and LoggingFeature.Verbosity.PAYLOAD_ANY, then inspect the attached threaddump and the Future.get() wait. Compare it with HEADERS_ONLY and the default connector. Done means the asynchronous request completes without hanging in the PAYLOAD_ANY and JdkConnectorProvider combination.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- networking
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 55/100