Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8280113

(dc) DatagramSocket.receive does not always throw when the channel is closed

XMLWordPrintable

    • 14
    • b11
    • generic
    • generic
    • Verified

        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


              alanb Alan Bateman
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              10 Start watching this issue

                Created:
                Updated:
                Resolved: