-
Bug
-
Resolution: Fixed
-
P3
-
17, 21
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8324694 | 17.0.12-oracle | Johny Jose | P3 | Resolved | Fixed | b04 |
JDK-8332045 | 17.0.12 | Goetz Lindenmaier | P3 | Resolved | Fixed | b03 |
ADDITIONAL SYSTEM INFORMATION :
Linux Xubuntu 21.10 x64 OpenJDK17.0.1
Linux Xubuntu 21.10 x64 GraalVM CE 21.3.0
Linux Xubuntu 21.10 x64 BellSoft 17.0.1
Raspberry Pi OS Bullseye armhf BellSoft 17.0.1
A DESCRIPTION OF THE PROBLEM :
A DatagramSocket.receive() blocked on receive does not always throw a SocketException when the Socket is closed. If the Socket has a setSoTimeout set to a positive number and two packets have been received and the socket is closed no exception will be thrown. Also true for MulticastSockets.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Open a DatagramSocket, set Socket timeout to a positive value, receive two DatagramPackets, and then close the Socket.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
It should throw a SocketException.
ACTUAL -
Program flow will proceed to the subsequent instruction and no Excpetion will be thrown.
---------- BEGIN SOURCE ----------
import java.io.*;
import java.net.*;
public class SocketBug {
int port = 56789;
Thread rxThread;
Thread txThread;
DatagramSocket rxSocket;
volatile boolean runFlag;
public SocketBug() throws IOException {
rxSocket = new DatagramSocket(port);
// must have a positive value timeout
rxSocket.setSoTimeout(5000);
rxThread = new Thread(() -> {
byte[] buf = new byte[64];
DatagramPacket packet = new DatagramPacket(buf,buf.length);
try {
while (runFlag) {
rxSocket.receive(packet);
if (runFlag)
System.out.println("rxThread: packet received");
else
throw new IOException(
"should have thrown SocketException");
}
} catch (IOException ioe) {
System.out.printf("rxThread: %s%n",ioe);
}
});
txThread = new Thread(() -> {
byte[] buf = new byte[64];
DatagramPacket packet = new DatagramPacket(buf,buf.length,
new InetSocketAddress("localhost",port));
try (DatagramSocket txSocket = new DatagramSocket()) {
// just to make sure rxThread is blocked on receive
Thread.sleep(200);
// must send two packets
txSocket.send(packet);
txSocket.send(packet);
System.out.println("txThread: packets sent");
} catch (IOException|InterruptedException ex) {
System.out.printf("txThread: %s%n",ex);
}
});
}
public void start() {
runFlag = true;
rxThread.start();
txThread.start();
}
public void stop() {
runFlag = false;
rxSocket.close();
}
public static void main(String[] args) {
try {
SocketBug bug = new SocketBug();
bug.start();
Thread.sleep(1000);
bug.stop();
} catch (IOException|InterruptedException ex) {
System.out.printf("main: %s%n",ex);
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Set a flag before closing the Socket and test that flag after Socket.receive().
FREQUENCY : always
Linux Xubuntu 21.10 x64 OpenJDK17.0.1
Linux Xubuntu 21.10 x64 GraalVM CE 21.3.0
Linux Xubuntu 21.10 x64 BellSoft 17.0.1
Raspberry Pi OS Bullseye armhf BellSoft 17.0.1
A DESCRIPTION OF THE PROBLEM :
A DatagramSocket.receive() blocked on receive does not always throw a SocketException when the Socket is closed. If the Socket has a setSoTimeout set to a positive number and two packets have been received and the socket is closed no exception will be thrown. Also true for MulticastSockets.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Open a DatagramSocket, set Socket timeout to a positive value, receive two DatagramPackets, and then close the Socket.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
It should throw a SocketException.
ACTUAL -
Program flow will proceed to the subsequent instruction and no Excpetion will be thrown.
---------- BEGIN SOURCE ----------
import java.io.*;
import java.net.*;
public class SocketBug {
int port = 56789;
Thread rxThread;
Thread txThread;
DatagramSocket rxSocket;
volatile boolean runFlag;
public SocketBug() throws IOException {
rxSocket = new DatagramSocket(port);
// must have a positive value timeout
rxSocket.setSoTimeout(5000);
rxThread = new Thread(() -> {
byte[] buf = new byte[64];
DatagramPacket packet = new DatagramPacket(buf,buf.length);
try {
while (runFlag) {
rxSocket.receive(packet);
if (runFlag)
System.out.println("rxThread: packet received");
else
throw new IOException(
"should have thrown SocketException");
}
} catch (IOException ioe) {
System.out.printf("rxThread: %s%n",ioe);
}
});
txThread = new Thread(() -> {
byte[] buf = new byte[64];
DatagramPacket packet = new DatagramPacket(buf,buf.length,
new InetSocketAddress("localhost",port));
try (DatagramSocket txSocket = new DatagramSocket()) {
// just to make sure rxThread is blocked on receive
Thread.sleep(200);
// must send two packets
txSocket.send(packet);
txSocket.send(packet);
System.out.println("txThread: packets sent");
} catch (IOException|InterruptedException ex) {
System.out.printf("txThread: %s%n",ex);
}
});
}
public void start() {
runFlag = true;
rxThread.start();
txThread.start();
}
public void stop() {
runFlag = false;
rxSocket.close();
}
public static void main(String[] args) {
try {
SocketBug bug = new SocketBug();
bug.start();
Thread.sleep(1000);
bug.stop();
} catch (IOException|InterruptedException ex) {
System.out.printf("main: %s%n",ex);
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Set a flag before closing the Socket and test that flag after Socket.receive().
FREQUENCY : always
- backported by
-
JDK-8324694 (dc) DatagramSocket.receive does not always throw when the channel is closed
- Resolved
-
JDK-8332045 (dc) DatagramSocket.receive does not always throw when the channel is closed
- Resolved
- links to
-
Commit openjdk/jdk17u-dev/4504b163
-
Commit openjdk/jdk/b6ecca12
-
Review openjdk/jdk17u-dev/2445
-
Review openjdk/jdk/12674
(1 links to)