# HG changeset patch # User robm # Date 1363220494 0 # Node ID 15ee12718efe582911329b09d00d2f2b9291df46 # Parent e269be167fae66ca796a1a4606b0e220dbb9345a 8009650: HttpClient available() check throws SocketException when connection has been closed Reviewed-by: chegar, khazra, dsamersoff Contributed-by: sdouglas@redhat.com diff -r e269be167fae -r 15ee12718efe jdk/src/share/classes/sun/net/www/http/HttpClient.java --- a/jdk/src/share/classes/sun/net/www/http/HttpClient.java Wed Mar 13 14:50:40 2013 -0700 +++ b/jdk/src/share/classes/sun/net/www/http/HttpClient.java Thu Mar 14 00:21:34 2013 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -121,7 +121,14 @@ public boolean reuse = false; // Traffic capture tool, if configured. See HttpCapture class for info - private HttpCapture capture = null; + private HttpCapture capture = null; + + private static final PlatformLogger logger = HttpURLConnection.getHttpLogger(); + private static void logFinest(String msg) { + if (logger.isLoggable(PlatformLogger.FINEST)) { + logger.finest(msg); + } + } /** * A NOP method kept for backwards binary compatibility @@ -266,8 +273,11 @@ if (ret != null && httpuc != null && httpuc.streaming() && httpuc.getRequestMethod() == "POST") { - if (!ret.available()) + if (!ret.available()) { + ret.inCache = false; + ret.closeServer(); ret = null; + } } if (ret != null) { @@ -279,10 +289,7 @@ ret.inCache = false; if (httpuc != null && ret.needsTunneling()) httpuc.setTunnelState(TUNNELING); - PlatformLogger logger = HttpURLConnection.getHttpLogger(); - if (logger.isLoggable(PlatformLogger.FINEST)) { - logger.finest("KeepAlive stream retrieved from the cache, " + ret); - } + logFinest("KeepAlive stream retrieved from the cache, " + ret); } } else { // We cannot return this connection to the cache as it's @@ -360,30 +367,33 @@ } } - protected synchronized boolean available() throws IOException { + protected synchronized boolean available() { boolean available = true; - int old = serverSocket.getSoTimeout(); - serverSocket.setSoTimeout(1); - BufferedInputStream tmpbuf = - new BufferedInputStream(serverSocket.getInputStream()); + int old = -1; - PlatformLogger logger = HttpURLConnection.getHttpLogger(); try { - int r = tmpbuf.read(); - if (r == -1) { - if (logger.isLoggable(PlatformLogger.FINEST)) { - logger.finest("HttpClient.available(): " + - "read returned -1: not available"); + try { + old = serverSocket.getSoTimeout(); + serverSocket.setSoTimeout(1); + BufferedInputStream tmpbuf = + new BufferedInputStream(serverSocket.getInputStream()); + int r = tmpbuf.read(); + if (r == -1) { + logFinest("HttpClient.available(): " + + "read returned -1: not available"); + available = false; } - available = false; + } catch (SocketTimeoutException e) { + logFinest("HttpClient.available(): " + + "SocketTimeout: its available"); + } finally { + if (old != -1) + serverSocket.setSoTimeout(old); } - } catch (SocketTimeoutException e) { - if (logger.isLoggable(PlatformLogger.FINEST)) { - logger.finest("HttpClient.available(): " + - "SocketTimeout: its available"); - } - } finally { - serverSocket.setSoTimeout(old); + } catch (IOException e) { + logFinest("HttpClient.available(): " + + "SocketException: not available"); + available = false; } return available; } @@ -865,10 +875,7 @@ if (isKeepingAlive()) { // Wrap KeepAliveStream if keep alive is enabled. - PlatformLogger logger = HttpURLConnection.getHttpLogger(); - if (logger.isLoggable(PlatformLogger.FINEST)) { - logger.finest("KeepAlive stream used: " + url); - } + logFinest("KeepAlive stream used: " + url); serverInput = new KeepAliveStream(serverInput, pi, cl, this); failedOnce = false; } diff -r e269be167fae -r 15ee12718efe jdk/test/sun/net/www/http/HttpClient/IsAvailable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/net/www/http/HttpClient/IsAvailable.java Thu Mar 14 00:21:34 2013 +0000 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8009650 + * @summary HttpClient available() check throws SocketException when connection + * has been closed + */ + +import java.net.URL; +import java.net.ServerSocket; +import sun.net.www.http.HttpClient; +import java.security.*; +import java.lang.reflect.Method; + +public class IsAvailable { + + public static void main(String[] args) throws Exception { + int readTimeout = 20; + ServerSocket ss = new ServerSocket(0); + + URL url1 = new URL("http://localhost:" + ss.getLocalPort()); + HttpClient c1 = HttpClient.New(url1); + + Method available = HttpClient.class. + getDeclaredMethod("available", null); + available.setAccessible(true); + + c1.setReadTimeout(readTimeout); + boolean a = (boolean) available.invoke(c1); + if (!a) { + throw new RuntimeException("connection should be available"); + } + if (c1.getReadTimeout() != readTimeout) { + throw new RuntimeException("read timeout has been altered"); + } + + c1.closeServer(); + + a = (boolean) available.invoke(c1); + if (a) { + throw new RuntimeException("connection shouldn't be available"); + } + + ss.close(); + } +}