CSR :
|
|
CSR :
|
|
CSR :
|
## Summary Change the behavior of the TLS stack to pass through `SocketException` instead of wrapping it into an SSLException. ## Problem OpenJDK 8 (up to 8u265 for OpenJDK and 8u251 for Oracle JDK), 9 and 10 imposed the following contract between the `sun.security.ssl.SSLSocketImpl` class and its clients (see [SSLSocketImpl.java#l69](http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/9204e03217f7/src/share/classes/sun/security/ssl/SSLSocketImpl.java#l69)): ``` * ERROR HANDLING GUIDELINES * (which exceptions to throw and catch and which not to throw and catch) * * . if there is an IOException (SocketException) when accessing the * underlying Socket, pass it through * * . do not throw IOExceptions, throw SSLExceptions (or a subclass) ``` The TLS stack would pass through `SocketException`s unchanged but would wrap other `IOException`s into `SSLException`s. However, this contract was changed without notice in OpenJDK 11 by the new TLS1.3 stack [JDK-8196584](https://bugs.openjdk.java.net/browse/JDK-8196584). The new implementation now started wrapping **all** `IOException`s including `SocketException`s into `SSLException`s. The error handling guidelines present in the OpenJDK implementations before 11 were used by the application layer to determine how to react to the exception. The application layer (e.g the popular [Apache HTTPClient library](https://hc.apache.org/httpcomponents-client-ga/httpclient/project-reports.html)) would consider `SocketException`s to be retry-able and retry the request. Starting with JDK 11, such applications started seeing unhandled "`SSLException: Broken Pipe`" exceptions because now `SocketException`s were converted to `SSLException`s. Apache HTTPClient for example reported this as "[HTTPCLIENT-2032: Sometimes get a broken pipe error in Java 11..](https://issues.apache.org/jira/browse/HTTPCLIENT-2032)". The general problem with the new implementation is that application are now unable to determine if a failure was due to a retry-able `SocketException` or a more permanent `SSLException`. The blast radius of this behavioural change became a lot wider after the new TLS 1.3 stack was downported to jdk 8. "[JDK-8214339: SSLSocketImpl erroneously wraps SocketException](https://bugs.openjdk.java.net/browse/JDK-8214339)" attempted to fix this issue, however, it was still wrapping `SocketException`s and passing them to the application layer as `SSLException`s. Consequently, the new issue "[JDK-8237578: JDK-8214339 (SSLSocketImpl wraps SocketException)" appears to not be fully fixed"](https://bugs.openjdk.java.net/browse/JDK-8237578) was raised which was finally fixed for jdk 17 but unfortunately had to be backed out immediately because it had missed to update some tests. During the backout discussion the initial reviewers came to the conclusion that a CSR should have been raised for JDK-8237578. Finally, this CSR has been created for [JDK-8259662](https://bugs.openjdk.java.net/browse/JDK-8259662) which is the redo of JDK-8237578. ## Solution - Change the implementation of `SSLSocketImpl` in the new TLS 1.3 stack back to the old error handling protocol defined in JDK 8 (see [PR-2057](https://git.openjdk.java.net/jdk/pull/2057)). - Add a comment back to `SSLSocketImpl` class which documents this behaviour: ``` /* * ERROR HANDLING GUIDELINES * (which exceptions to throw and catch and which not to throw and catch) * * - if there is an IOException (SocketException) when accessing the * underlying Socket, pass it through * * - do not throw IOExceptions, throw SSLExceptions (or a subclass) */ ``` ## Specification No specification change.
|