-
Bug
-
Resolution: Fixed
-
P4
-
13
-
b08
-
x86
-
os_x
-
Not verified
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8278206 | 11.0.15-oracle | Yoshiki Sato | P4 | Resolved | Fixed | b02 |
JDK-8277035 | 11.0.14 | Andrew Hughes | P4 | Resolved | Fixed | b03 |
ADDITIONAL SYSTEM INFORMATION :
It happens also on linux (originally discovered in QA environment), but I am able to reproduce on a mac.
A DESCRIPTION OF THE PROBLEM :
This bug is VERY similar toJDK-8221395, except that this bug only happens with HTTP/2 protocol using a proxy tunnel. The JDK-8221395 test case only fixes the HTTP/1 case, so I modified it to use HTTP/2 to reproduce this issue.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. git clone https://github.com/tinyproxy/tinyproxy.git # clone tinyproxy repo
2. cd tinyproxy # go into tinyproxy checkout
3. ./autogen.sh && ./configure && make # build tinyproxy
4. src/tinyproxy -d -c etc/tinyproxy.conf # start tinyproxy server, it will listen on port 8888
5. java SocketSandbox.java # start socket server (repro)
6. telnet localhost 59090
Wait a few minutes, for the connection to time out. You'll see tinyproxy terminate the connection to nghttp2.org, but netstat will show a leaked TUNNEL to the proxy in CLOSE_WAIT state, it will look something like this.
tcp4 24 0 127.0.0.1.58252 127.0.0.1.8888 CLOSE_WAIT
This will never get close()'d.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The socket connection to the proxy should eventually be closed.
ACTUAL -
The socket connection to the proxy remains in CLOSE_WAIT indefinitely until the java process ends. There is always some small amount of bytes (e.g. 24) in Recv-Q.
---------- BEGIN SOURCE ----------
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.ProxySelector;
import java.net.ServerSocket;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpClient.Version;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
public class SocketSandbox {
public static void main(String[] args) throws Exception {
try (var listener = new ServerSocket(59090)) {
System.out.println("Server is running...");
while (true) {
try (var socket = listener.accept()) {
HttpClient client = HttpClient.newBuilder()
.version(Version.HTTP_2)
.proxy(ProxySelector.of(new InetSocketAddress("127.0.0.1", 8888)))
.build();
HttpRequest request = HttpRequest.newBuilder(URI.create("https://nghttp2.org/httpbin/anything")).build();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
var out = new PrintWriter(socket.getOutputStream(), true);
out.println(String.format("Response HTTP status: %s", response.statusCode()));
}
}
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
This issue can be worked around by explicitly disabling the http/2 protocol via Version.HTTP_1_1. The bug does not happen at all, except with HTTP/2, and only when a proxy is used.
FREQUENCY : always
It happens also on linux (originally discovered in QA environment), but I am able to reproduce on a mac.
A DESCRIPTION OF THE PROBLEM :
This bug is VERY similar to
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. git clone https://github.com/tinyproxy/tinyproxy.git # clone tinyproxy repo
2. cd tinyproxy # go into tinyproxy checkout
3. ./autogen.sh && ./configure && make # build tinyproxy
4. src/tinyproxy -d -c etc/tinyproxy.conf # start tinyproxy server, it will listen on port 8888
5. java SocketSandbox.java # start socket server (repro)
6. telnet localhost 59090
Wait a few minutes, for the connection to time out. You'll see tinyproxy terminate the connection to nghttp2.org, but netstat will show a leaked TUNNEL to the proxy in CLOSE_WAIT state, it will look something like this.
tcp4 24 0 127.0.0.1.58252 127.0.0.1.8888 CLOSE_WAIT
This will never get close()'d.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The socket connection to the proxy should eventually be closed.
ACTUAL -
The socket connection to the proxy remains in CLOSE_WAIT indefinitely until the java process ends. There is always some small amount of bytes (e.g. 24) in Recv-Q.
---------- BEGIN SOURCE ----------
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.ProxySelector;
import java.net.ServerSocket;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpClient.Version;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
public class SocketSandbox {
public static void main(String[] args) throws Exception {
try (var listener = new ServerSocket(59090)) {
System.out.println("Server is running...");
while (true) {
try (var socket = listener.accept()) {
HttpClient client = HttpClient.newBuilder()
.version(Version.HTTP_2)
.proxy(ProxySelector.of(new InetSocketAddress("127.0.0.1", 8888)))
.build();
HttpRequest request = HttpRequest.newBuilder(URI.create("https://nghttp2.org/httpbin/anything")).build();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
var out = new PrintWriter(socket.getOutputStream(), true);
out.println(String.format("Response HTTP status: %s", response.statusCode()));
}
}
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
This issue can be worked around by explicitly disabling the http/2 protocol via Version.HTTP_1_1. The bug does not happen at all, except with HTTP/2, and only when a proxy is used.
FREQUENCY : always
- backported by
-
JDK-8277035 HttpClient leaves HTTP/2 sockets in CLOSE_WAIT, when using proxy tunnel
- Resolved
-
JDK-8278206 HttpClient leaves HTTP/2 sockets in CLOSE_WAIT, when using proxy tunnel
- Resolved