-
Bug
-
Resolution: Fixed
-
P2
-
1.0.2
-
None
-
ventura
-
generic
-
generic
When Thread.interrupt is called on a thread which is blocked on an
SSLSocket.read then the interrupt exception is masked by JSSE and
the read method returns with an end-of-stream error. I expect the
interrupt exception to be thrown, as is done for non-SSL sockets.
The LDAP provider in JNDI depends on JSSE and has a requirement to
interrupt an SSLSocket.read operation in order to switch input streams.
This can occur, for example, when a TLS connection has been established
over an existing socket (without client authentication) and the JNDI user
wishes to perform client authentication using a public key certificate.
The problem can be demonstrated using the program below.
Here is a trace of the plain socket case: the interrupt is thrown,
as expected.
% /usr/local/java/jdk1.4/solsparc/bin/java
TestSocketInterrupt oasis.ireland.sun.com 389
Establishing a plain connection ...
Connected to: oasis.ireland.sun.com:389
Pausing for 5 seconds ...
Reading from input stream ...
Interrupting reader thread
java.io.InterruptedIOException: Interrupted system call
at java.net.SocketInputStream.socketRead(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:99)
at java.net.SocketInputStream.read(SocketInputStream.java:115)
at TestSocketInterrupt$Reader.run(TestSocketInterrupt.java:84)
Here is a trace of the SSL socket case: the interrupt is masked.
% /usr/local/java/jdk1.4/solsparc/bin/java
TestSocketInterrupt -ssl oasis.ireland.sun.com 636
Establishing an SSL connection ...
Connected to: oasis.ireland.sun.com:636
Pausing for 5 seconds ...
Reading from input stream ...
Interrupting reader thread
End-of-stream detected
/*
* Copyright (c) 2000. Sun Microsystems, Inc. All rights reserved.
*/
import java.io.InputStream;
import java.net.Socket;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
/**
* Demonstrate that an SSL socket blocked on a read cannot be
* interrupted correctly.
*
* Usage: java TestSocketInterrupt [-ssl] <hostname> <port number>
*
* Example: java TestSocketInterrupt -ssl oasis.ireland.sun.com 636
*
* Requires: JDK 1.4 (Merlin)
*/
public class TestSocketInterrupt {
public static void main(String[] args) {
boolean useSSL;
String host;
int port;
Socket socket;
if (args[0].equals("-ssl")) {
useSSL = true;
host = args[1];
port = Integer.parseInt(args[2]);
} else {
useSSL = false;
host = args[0];
port = Integer.parseInt(args[1]);
}
try {
if (useSSL) {
System.out.println("Establishing an SSL connection ...");
SSLContext sslCtx = SSLContext.getInstance("TLS");
sslCtx.init(null, null, null);
SSLSocketFactory factory = sslCtx.getSocketFactory();
socket = (Socket) factory.createSocket(host, port);
} else {
System.out.println("Establishing a plain connection ...");
socket = new Socket(host, port);
}
InputStream inStream = socket.getInputStream();
System.out.println("Connected to: " + host + ":" + port);
Reader reader = new Reader(inStream);
reader.start();
// sleep for 5 seconds
System.out.println("Pausing for 5 seconds ...");
try {
Thread.sleep(5 * 1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Interrupting reader thread");
reader.interrupt();
} catch (Exception e) {
e.printStackTrace();
}
}
static class Reader extends Thread {
private InputStream inStream;
public Reader(InputStream inStream) {
this.inStream = inStream;
}
public void run() {
try {
System.out.println("Reading from input stream ...");
if (inStream.read() == -1) {
System.out.println("End-of-stream detected");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
SSLSocket.read then the interrupt exception is masked by JSSE and
the read method returns with an end-of-stream error. I expect the
interrupt exception to be thrown, as is done for non-SSL sockets.
The LDAP provider in JNDI depends on JSSE and has a requirement to
interrupt an SSLSocket.read operation in order to switch input streams.
This can occur, for example, when a TLS connection has been established
over an existing socket (without client authentication) and the JNDI user
wishes to perform client authentication using a public key certificate.
The problem can be demonstrated using the program below.
Here is a trace of the plain socket case: the interrupt is thrown,
as expected.
% /usr/local/java/jdk1.4/solsparc/bin/java
TestSocketInterrupt oasis.ireland.sun.com 389
Establishing a plain connection ...
Connected to: oasis.ireland.sun.com:389
Pausing for 5 seconds ...
Reading from input stream ...
Interrupting reader thread
java.io.InterruptedIOException: Interrupted system call
at java.net.SocketInputStream.socketRead(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:99)
at java.net.SocketInputStream.read(SocketInputStream.java:115)
at TestSocketInterrupt$Reader.run(TestSocketInterrupt.java:84)
Here is a trace of the SSL socket case: the interrupt is masked.
% /usr/local/java/jdk1.4/solsparc/bin/java
TestSocketInterrupt -ssl oasis.ireland.sun.com 636
Establishing an SSL connection ...
Connected to: oasis.ireland.sun.com:636
Pausing for 5 seconds ...
Reading from input stream ...
Interrupting reader thread
End-of-stream detected
/*
* Copyright (c) 2000. Sun Microsystems, Inc. All rights reserved.
*/
import java.io.InputStream;
import java.net.Socket;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
/**
* Demonstrate that an SSL socket blocked on a read cannot be
* interrupted correctly.
*
* Usage: java TestSocketInterrupt [-ssl] <hostname> <port number>
*
* Example: java TestSocketInterrupt -ssl oasis.ireland.sun.com 636
*
* Requires: JDK 1.4 (Merlin)
*/
public class TestSocketInterrupt {
public static void main(String[] args) {
boolean useSSL;
String host;
int port;
Socket socket;
if (args[0].equals("-ssl")) {
useSSL = true;
host = args[1];
port = Integer.parseInt(args[2]);
} else {
useSSL = false;
host = args[0];
port = Integer.parseInt(args[1]);
}
try {
if (useSSL) {
System.out.println("Establishing an SSL connection ...");
SSLContext sslCtx = SSLContext.getInstance("TLS");
sslCtx.init(null, null, null);
SSLSocketFactory factory = sslCtx.getSocketFactory();
socket = (Socket) factory.createSocket(host, port);
} else {
System.out.println("Establishing a plain connection ...");
socket = new Socket(host, port);
}
InputStream inStream = socket.getInputStream();
System.out.println("Connected to: " + host + ":" + port);
Reader reader = new Reader(inStream);
reader.start();
// sleep for 5 seconds
System.out.println("Pausing for 5 seconds ...");
try {
Thread.sleep(5 * 1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Interrupting reader thread");
reader.interrupt();
} catch (Exception e) {
e.printStackTrace();
}
}
static class Reader extends Thread {
private InputStream inStream;
public Reader(InputStream inStream) {
this.inStream = inStream;
}
public void run() {
try {
System.out.println("Reading from input stream ...");
if (inStream.read() == -1) {
System.out.println("End-of-stream detected");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
- duplicates
-
JDK-4456039 Setting timeouts on SSLSockets immediately return null after timeout occurs.
- Closed