Fix for HttpURLConnection not always throwing SocketTimeoutException Contains upstream changes: Okio: https://github.com/square/okio/pull/154 OkHttp: https://github.com/square/okhttp/pull/1698 (pending) Bug: 21396523 (cherry-picked from commit b5f9076b16fcc41c3dad31aecfdcfd962a7a1f75) Change-Id: I4d44e973f906d41a622598e2293d4026fc1ed039
diff --git a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/HttpOverSpdyTest.java b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/HttpOverSpdyTest.java index ab8f3c9..be9f10e 100644 --- a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/HttpOverSpdyTest.java +++ b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/HttpOverSpdyTest.java
@@ -32,6 +32,7 @@ import java.net.Authenticator; import java.net.CookieManager; import java.net.HttpURLConnection; +import java.net.SocketTimeoutException; import java.net.URL; import java.util.Arrays; import java.util.Collections; @@ -307,8 +308,8 @@ try { readAscii(connection.getInputStream(), Integer.MAX_VALUE); fail("Should have timed out!"); - } catch (IOException e){ - assertEquals("timeout", e.getMessage()); + } catch (SocketTimeoutException expected){ + assertEquals("timeout", expected.getMessage()); } }
diff --git a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/URLConnectionTest.java b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/URLConnectionTest.java index 7caf404..3be5a2d 100644 --- a/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/URLConnectionTest.java +++ b/okhttp-tests/src/test/java/com/squareup/okhttp/internal/http/URLConnectionTest.java
@@ -57,6 +57,7 @@ import java.net.ServerSocket; import java.net.Socket; import java.net.SocketAddress; +import java.net.SocketTimeoutException; import java.net.URI; import java.net.URL; import java.net.URLConnection; @@ -2213,7 +2214,7 @@ try { in.read(); // if Content-Length was accurate, this would return -1 immediately fail(); - } catch (IOException expected) { + } catch (SocketTimeoutException expected) { } } @@ -2249,7 +2250,7 @@ byte[] data = new byte[16 * 1024 * 1024]; // 16 MiB. out.write(data); fail(); - } catch (IOException expected) { + } catch (SocketTimeoutException expected) { } }
diff --git a/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/SpdyStream.java b/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/SpdyStream.java index 05ce57a..cdbd7aa 100644 --- a/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/SpdyStream.java +++ b/okhttp/src/main/java/com/squareup/okhttp/internal/spdy/SpdyStream.java
@@ -19,6 +19,7 @@ import java.io.EOFException; import java.io.IOException; import java.io.InterruptedIOException; +import java.net.SocketTimeoutException; import java.util.ArrayList; import java.util.List; import okio.AsyncTimeout; @@ -600,8 +601,16 @@ closeLater(ErrorCode.CANCEL); } - public void exitAndThrowIfTimedOut() throws InterruptedIOException { - if (exit()) throw new InterruptedIOException("timeout"); + @Override protected IOException newTimeoutException(IOException cause) { + SocketTimeoutException socketTimeoutException = new SocketTimeoutException("timeout"); + if (cause != null) { + socketTimeoutException.initCause(cause); + } + return socketTimeoutException; + } + + public void exitAndThrowIfTimedOut() throws IOException { + if (exit()) throw newTimeoutException(null /* cause */); } } }
diff --git a/okio/okio/src/main/java/okio/AsyncTimeout.java b/okio/okio/src/main/java/okio/AsyncTimeout.java index cda6ff4..dbadfb4 100644 --- a/okio/okio/src/main/java/okio/AsyncTimeout.java +++ b/okio/okio/src/main/java/okio/AsyncTimeout.java
@@ -241,22 +241,36 @@ } /** - * Throws an InterruptedIOException if {@code throwOnTimeout} is true and a - * timeout occurred. + * Throws an IOException if {@code throwOnTimeout} is {@code true} and a + * timeout occurred. See {@link #newTimeoutException(java.io.IOException)} + * for the type of exception thrown. */ final void exit(boolean throwOnTimeout) throws IOException { boolean timedOut = exit(); - if (timedOut && throwOnTimeout) throw new InterruptedIOException("timeout"); + if (timedOut && throwOnTimeout) throw newTimeoutException(null); } /** - * Returns either {@code cause} or an InterruptedIOException that's caused by - * {@code cause} if a timeout occurred. + * Returns either {@code cause} or an IOException that's caused by + * {@code cause} if a timeout occurred. See + * {@link #newTimeoutException(java.io.IOException)} for the type of + * exception returned. */ final IOException exit(IOException cause) throws IOException { if (!exit()) return cause; + return newTimeoutException(cause); + } + + /** + * Returns an {@link IOException} to represent a timeout. By default this method returns + * {@link java.io.InterruptedIOException}. If {@code cause} is non-null it is set as the cause of + * the returned exception. + */ + protected IOException newTimeoutException(IOException cause) { InterruptedIOException e = new InterruptedIOException("timeout"); - e.initCause(cause); + if (cause != null) { + e.initCause(cause); + } return e; }
diff --git a/okio/okio/src/main/java/okio/Okio.java b/okio/okio/src/main/java/okio/Okio.java index df3f8bf..1eba4e0 100644 --- a/okio/okio/src/main/java/okio/Okio.java +++ b/okio/okio/src/main/java/okio/Okio.java
@@ -21,8 +21,10 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.InterruptedIOException; import java.io.OutputStream; import java.net.Socket; +import java.net.SocketTimeoutException; import java.util.logging.Level; import java.util.logging.Logger; @@ -201,6 +203,14 @@ private static AsyncTimeout timeout(final Socket socket) { return new AsyncTimeout() { + @Override protected IOException newTimeoutException(IOException cause) { + InterruptedIOException ioe = new SocketTimeoutException("timeout"); + if (cause != null) { + ioe.initCause(cause); + } + return ioe; + } + @Override protected void timedOut() { try { socket.close();
diff --git a/okio/okio/src/test/java/okio/SocketTimeoutTest.java b/okio/okio/src/test/java/okio/SocketTimeoutTest.java index 6bb73e6..23ea211 100644 --- a/okio/okio/src/test/java/okio/SocketTimeoutTest.java +++ b/okio/okio/src/test/java/okio/SocketTimeoutTest.java
@@ -18,10 +18,10 @@ import java.io.EOFException; import java.io.IOException; import java.io.InputStream; -import java.io.InterruptedIOException; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; +import java.net.SocketTimeoutException; import java.util.concurrent.TimeUnit; import org.junit.Test; @@ -50,7 +50,7 @@ try { source.require(ONE_MB); fail(); - } catch (InterruptedIOException expected) { + } catch (SocketTimeoutException expected) { } socket.close(); } @@ -75,7 +75,7 @@ sink.write(new Buffer().write(data), data.length); sink.flush(); fail(); - } catch (InterruptedIOException expected) { + } catch (SocketTimeoutException expected) { } long elapsed = System.nanoTime() - start; socket.close();