diff --git a/okhttp/src/main/java/okhttp3/internal/connection/RealConnection.kt b/okhttp/src/main/java/okhttp3/internal/connection/RealConnection.kt index 4dd219bbeeb9..2af046146be2 100644 --- a/okhttp/src/main/java/okhttp3/internal/connection/RealConnection.kt +++ b/okhttp/src/main/java/okhttp3/internal/connection/RealConnection.kt @@ -631,9 +631,11 @@ class RealConnection( fun isHealthy(doExtensiveChecks: Boolean): Boolean { val nowNs = System.nanoTime() + val rawSocket = this.rawSocket!! val socket = this.socket!! val source = this.source!! - if (socket.isClosed || socket.isInputShutdown || socket.isOutputShutdown) { + if (rawSocket.isClosed || socket.isClosed || socket.isInputShutdown || + socket.isOutputShutdown) { return false } diff --git a/okhttp/src/test/java/okhttp3/CallTest.java b/okhttp/src/test/java/okhttp3/CallTest.java index 1cb2e4e800ef..28e4855142b3 100644 --- a/okhttp/src/test/java/okhttp3/CallTest.java +++ b/okhttp/src/test/java/okhttp3/CallTest.java @@ -91,6 +91,7 @@ import static java.net.CookiePolicy.ACCEPT_ORIGINAL_SERVER; import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; import static okhttp3.CipherSuite.TLS_DH_anon_WITH_AES_128_GCM_SHA256; import static okhttp3.TestUtil.awaitGarbageCollection; import static okhttp3.internal.Internal.addHeaderLenient; @@ -3836,6 +3837,37 @@ private RequestBody requestBody(final boolean chunked, final long size, final in requestBodyThrowsUnrelatedToNetwork(); } + /** + * This test cancels the call just after the response body ends. In effect we end up with a + * connection that returns to the connection pool with the underlying socket closed. This relies + * on an implementation detail so it might not be a valid test case in the future. + */ + @Test public void cancelAfterResponseBodyEnd() throws Exception { + enableTls(); + server.enqueue(new MockResponse().setBody("abc")); + server.enqueue(new MockResponse().setBody("def")); + + client = client.newBuilder() + .protocols(singletonList(Protocol.HTTP_1_1)) + .build(); + + OkHttpClient cancelClient = client.newBuilder() + .eventListener(new EventListener() { + @Override public void responseBodyEnd(Call call, long byteCount) { + call.cancel(); + } + }) + .build(); + + Call call = cancelClient.newCall(new Request.Builder() + .url(server.url("/")) + .build()); + Response response = call.execute(); + assertThat(response.body().string()).isEqualTo("abc"); + + executeSynchronously("/").assertCode(200); + } + /** https://github.com/square/okhttp/issues/4583 */ @Test public void lateCancelCallsOnFailure() throws Exception { server.enqueue(new MockResponse()