8236464: SO_LINGER option is ignored by SSLSocket in JDK 11

Reviewed-by: ascarpino
This commit is contained in:
Xue-Lei Andrew Fan 2020-04-24 13:30:47 -07:00
parent 88f3861cb7
commit bfcb340606
2 changed files with 42 additions and 37 deletions

View file

@ -619,6 +619,15 @@ public final class SSLSocketImpl
}
}
// Deliver the user_canceled alert and the close notify alert.
closeNotify(useUserCanceled);
if (!isInputShutdown()) {
bruteForceCloseInput(hasCloseReceipt);
}
}
void closeNotify(boolean useUserCanceled) throws IOException {
// Need a lock here so that the user_canceled alert and the
// close_notify alert can be delivered together.
int linger = getSoLinger();
@ -633,7 +642,7 @@ public final class SSLSocketImpl
conContext.outputRecord.recordLock.tryLock(
linger, TimeUnit.SECONDS)) {
try {
handleClosedNotifyAlert(useUserCanceled);
deliverClosedNotify(useUserCanceled);
} finally {
conContext.outputRecord.recordLock.unlock();
}
@ -687,18 +696,14 @@ public final class SSLSocketImpl
} else {
conContext.outputRecord.recordLock.lock();
try {
handleClosedNotifyAlert(useUserCanceled);
deliverClosedNotify(useUserCanceled);
} finally {
conContext.outputRecord.recordLock.unlock();
}
}
if (!isInputShutdown()) {
bruteForceCloseInput(hasCloseReceipt);
}
}
private void handleClosedNotifyAlert(
private void deliverClosedNotify(
boolean useUserCanceled) throws IOException {
try {
// send a user_canceled alert if needed.

View file

@ -238,7 +238,7 @@ final class TransportContext implements ConnectionContext {
(handshakeContext instanceof PostHandshakeContext);
}
// Note: close_notify is delivered as a warning alert.
// Note: Don't use this method for close_nofity, use closeNotify() instead.
void warning(Alert alert) {
// For initial handshaking, don't send a warning alert message to peer
// if handshaker has not started.
@ -254,6 +254,33 @@ final class TransportContext implements ConnectionContext {
}
}
// Note: close_notify is delivered as a warning alert.
void closeNotify(boolean isUserCanceled) throws IOException {
// Socket transport is special because of the SO_LINGER impact.
if (transport instanceof SSLSocketImpl) {
((SSLSocketImpl)transport).closeNotify(isUserCanceled);
} else {
// Need a lock here so that the user_canceled alert and the
// close_notify alert can be delivered together.
outputRecord.recordLock.lock();
try {
try {
// send a user_canceled alert if needed.
if (isUserCanceled) {
warning(Alert.USER_CANCELED);
}
// send a close_notify alert
warning(Alert.CLOSE_NOTIFY);
} finally {
outputRecord.close();
}
} finally {
outputRecord.recordLock.unlock();
}
}
}
SSLException fatal(Alert alert,
String diagnostic) throws SSLException {
return fatal(alert, diagnostic, null);
@ -501,17 +528,7 @@ final class TransportContext implements ConnectionContext {
}
if (needCloseNotify) {
outputRecord.recordLock.lock();
try {
try {
// send a close_notify alert
warning(Alert.CLOSE_NOTIFY);
} finally {
outputRecord.close();
}
} finally {
outputRecord.recordLock.unlock();
}
closeNotify(false);
}
}
}
@ -547,24 +564,7 @@ final class TransportContext implements ConnectionContext {
useUserCanceled = true;
}
// Need a lock here so that the user_canceled alert and the
// close_notify alert can be delivered together.
outputRecord.recordLock.lock();
try {
try {
// send a user_canceled alert if needed.
if (useUserCanceled) {
warning(Alert.USER_CANCELED);
}
// send a close_notify alert
warning(Alert.CLOSE_NOTIFY);
} finally {
outputRecord.close();
}
} finally {
outputRecord.recordLock.unlock();
}
closeNotify(useUserCanceled);
}
// Note; HandshakeStatus.FINISHED status is retrieved in other places.