JDK-5067294 : One case still fails after the fix for 5039967
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 5.0
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2004-06-23
  • Updated: 2004-06-25
  • Resolved: 2004-06-25
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
5.0 b58Fixed
Related Reports
Relates :  
Description
The fix for bug
5039967: Repeated authentication for each jar with multi-jar applet/client authentication only partially fixed the problem. There is one case that still fails. 

I recorded an asyc close of socket by the gc calling MeteredStream.finalize() (see details in bug 5039967 description) that happens when the response body is empty.

Here's what my fix looked like:

750             String requestLine = requests.getKey(0);
751
752             if (cl == -1 && ((requestLine != null &&
753                  (requestLine.startsWith("HEAD"))) ||
754                 code == HttpURLConnection.HTTP_NOT_MODIFIED ||
755                 code == HttpURLConnection.HTTP_NO_CONTENT)) {
756                 cl = 0;
757             }
758

at one point, I didn't have cl == -1 in the if clause. I put it in later just to be "safe". well, it turns out that doing that is incorrect, because if the request is "HEAD", the content-length will be set to the same value as if it is a "GET" request, but the response body will be empty. So MeteredStream or KeepAliveStream could still be created when the connection is reused. When that stream goes out of scope and be GCed, the reused connection could be closed from underneath. if I remove the cl == -1 check, plugin tests will pass. 

###@###.### 2004-06-23

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: generic tiger-rc FIXED IN: tiger-rc INTEGRATED IN: tiger-b58 tiger-rc
17-07-2004

EVALUATION Here is what's going on: HttpURLConnection has a special case for HEAD request and a few others that looks like the following: if (method.equals("HEAD") || cl == 0 || respCode == HTTP_NOT_MODIFIED || respCode == HTTP_NO_CONTENT) { if (pi != null) { pi.finishTracking(); pi = null; } http.finished(); http = null; inputStream = new EmptyInputStream(); ...... That is, when http.finished() is called, the underlying connection will be put into cache. and an EmptyInputStream created and returned later. But before this happens, HttpClient.parseHttpHeader is called to parse the response header. Because of the cl==-1 check and the method==HEAD, cl will not be set to 0, instead it will be a positive number. So a KeepAliveStream will be created. However, later at one point, the KeepAliveStream will go out of scope and be garbage collected. At which point, its close() method is called. because content-length>0, i.e. expected response body is >0, but avaible() bytes to be read is 0, so the close() method will actually close the underlying socket. That's why we saw the "IOException: stream closed" while reading the next http response body. The reason why a MeteredStream instead of a KeepAliveStream is shown on the stack is because KeepAliveStream doesn't overwrite the read() method in MeteredStream. Will fix for Tiger-rc. ###@###.### 2004-06-23
23-06-2004