test/jdk/java/net/MulticastSocket/UnreferencedMulticastSockets.java
changeset 58423 54de0c861d32
parent 55047 3131927311ee
equal deleted inserted replaced
58422:d7dbabd226ff 58423:54de0c861d32
    48 import java.nio.file.Path;
    48 import java.nio.file.Path;
    49 import java.nio.file.Paths;
    49 import java.nio.file.Paths;
    50 import java.util.ArrayDeque;
    50 import java.util.ArrayDeque;
    51 import java.util.List;
    51 import java.util.List;
    52 import java.util.Optional;
    52 import java.util.Optional;
       
    53 import java.util.concurrent.Phaser;
    53 import java.util.concurrent.TimeUnit;
    54 import java.util.concurrent.TimeUnit;
    54 
    55 
    55 import jdk.test.lib.net.IPSupport;
    56 import jdk.test.lib.net.IPSupport;
    56 
    57 
    57 import com.sun.management.UnixOperatingSystemMXBean;
    58 import com.sun.management.UnixOperatingSystemMXBean;
    70 
    71 
    71     // Server to echo a datagram packet
    72     // Server to echo a datagram packet
    72     static class Server implements Runnable {
    73     static class Server implements Runnable {
    73 
    74 
    74         MulticastSocket ss;
    75         MulticastSocket ss;
    75 
    76         final int port;
       
    77         final Phaser phaser = new Phaser(2);
    76         Server() throws IOException {
    78         Server() throws IOException {
       
    79             InetAddress loopback = InetAddress.getLoopbackAddress();
    77             InetSocketAddress serverAddress =
    80             InetSocketAddress serverAddress =
    78                 new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
    81                 new InetSocketAddress(loopback, 0);
    79             ss = new MulticastSocket(serverAddress);
    82             ss = new MulticastSocket(serverAddress);
       
    83             port = ss.getLocalPort();
    80             System.out.printf("  DatagramServer addr: %s: %d%n",
    84             System.out.printf("  DatagramServer addr: %s: %d%n",
    81                     this.getHost(), this.getPort());
    85                     this.getHost(), this.getPort());
    82             pendingSockets.add(new NamedWeak(ss, pendingQueue, "serverMulticastSocket"));
    86             pendingSockets.add(new NamedWeak(ss, pendingQueue, "serverMulticastSocket"));
    83             extractRefs(ss, "serverMulticastSocket");
    87             extractRefs(ss, "serverMulticastSocket");
    84         }
    88         }
    87             InetAddress localhost = InetAddress.getLoopbackAddress();
    91             InetAddress localhost = InetAddress.getLoopbackAddress();
    88             return localhost;
    92             return localhost;
    89         }
    93         }
    90 
    94 
    91         int getPort() {
    95         int getPort() {
    92             return ss.getLocalPort();
    96             return port;
    93         }
    97         }
    94 
    98 
    95         // Receive a byte and send back a byte
    99         // Receive a byte and send back a byte
    96         public void run() {
   100         public void run() {
    97             try {
   101             try {
    98                 byte[] buffer = new byte[50];
   102                 byte[] buffer = new byte[50];
    99                 DatagramPacket p = new DatagramPacket(buffer, buffer.length);
   103                 DatagramPacket p = new DatagramPacket(buffer, buffer.length);
   100                 ss.receive(p);
   104                 ss.receive(p);
       
   105                 System.out.printf("Server: ping received from: %s%n", p.getSocketAddress());
       
   106                 phaser.arriveAndAwaitAdvance(); // await the client...
   101                 buffer[0] += 1;
   107                 buffer[0] += 1;
       
   108                 System.out.printf("Server: sending echo to: %s%n", p.getSocketAddress());
   102                 ss.send(p);         // send back +1
   109                 ss.send(p);         // send back +1
   103 
   110 
       
   111                 System.out.printf("Server: awaiting client%n");
       
   112                 phaser.arriveAndAwaitAdvance(); // await the client...
   104                 // do NOT close but 'forget' the socket reference
   113                 // do NOT close but 'forget' the socket reference
       
   114                 System.out.printf("Server: forgetting socket...%n");
   105                 ss = null;
   115                 ss = null;
   106             } catch (Exception ioe) {
   116             } catch (Throwable ioe) {
   107                 ioe.printStackTrace();
   117                 ioe.printStackTrace();
   108             }
   118             }
   109         }
   119         }
   110     }
   120     }
   111 
   121 
   112     public static void main(String args[]) throws Exception {
   122     public static void main(String args[]) throws Exception {
   113         IPSupport.throwSkippedExceptionIfNonOperational();
   123         IPSupport.throwSkippedExceptionIfNonOperational();
   114 
   124 
       
   125         InetSocketAddress clientAddress =
       
   126                 new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
       
   127 
   115         // Create and close a MulticastSocket to warm up the FD count for side effects.
   128         // Create and close a MulticastSocket to warm up the FD count for side effects.
   116         try (MulticastSocket s = new MulticastSocket(0)) {
   129         try (MulticastSocket s = new MulticastSocket(clientAddress)) {
   117             // no-op; close immediately
   130             // no-op; close immediately
   118             s.getLocalPort();   // no-op
   131             s.getLocalPort();   // no-op
   119         }
   132         }
   120 
   133 
   121         long fdCount0 = getFdCount();
   134         long fdCount0 = getFdCount();
   124         // start a server
   137         // start a server
   125         Server svr = new Server();
   138         Server svr = new Server();
   126         Thread thr = new Thread(svr);
   139         Thread thr = new Thread(svr);
   127         thr.start();
   140         thr.start();
   128 
   141 
   129         MulticastSocket client = new MulticastSocket(0);
   142         // It is possible under some circumstances that the client
   130         System.out.printf("  client bound port: %d%n", client.getLocalPort());
   143         // might get bound to the same port than the server: this
       
   144         // would make the test fail - so if this happen we try to
       
   145         // bind to a specific port by incrementing the server port.
       
   146         MulticastSocket client = null;
       
   147         int serverPort = svr.getPort();
       
   148         int maxtries = 20;
       
   149         for (int i = 0; i < maxtries; i++) {
       
   150             try {
       
   151                 System.out.printf("Trying to bind client to: %s%n", clientAddress);
       
   152                 client = new MulticastSocket(clientAddress);
       
   153                 if (client.getLocalPort() != svr.getPort()) break;
       
   154                 client.close();
       
   155             } catch (IOException x) {
       
   156                 System.out.printf("Couldn't create client after %d attempts: %s%n", i, x);
       
   157                 if (i == maxtries) throw x;
       
   158             }
       
   159             if (i == maxtries) {
       
   160                 String msg = String.format("Couldn't create client after %d attempts", i);
       
   161                 System.out.println(msg);
       
   162                 throw new AssertionError(msg);
       
   163             }
       
   164             clientAddress = new InetSocketAddress(clientAddress.getAddress(), serverPort + i);
       
   165         }
       
   166 
       
   167         System.out.printf("  client bound port: %s:%d%n",
       
   168                 client.getLocalAddress(), client.getLocalPort());
   131         client.connect(svr.getHost(), svr.getPort());
   169         client.connect(svr.getHost(), svr.getPort());
   132         pendingSockets.add(new NamedWeak(client, pendingQueue, "clientMulticastSocket"));
   170         pendingSockets.add(new NamedWeak(client, pendingQueue, "clientMulticastSocket"));
   133         extractRefs(client, "clientMulticastSocket");
   171         extractRefs(client, "clientMulticastSocket");
   134 
   172 
   135         byte[] msg = new byte[1];
   173         byte[] msg = new byte[1];
   136         msg[0] = 1;
   174         msg[0] = 1;
   137         DatagramPacket p = new DatagramPacket(msg, msg.length, svr.getHost(), svr.getPort());
   175         DatagramPacket p = new DatagramPacket(msg, msg.length, svr.getHost(), svr.getPort());
   138         client.send(p);
   176         client.send(p);
       
   177         System.out.printf("  ping sent to: %s:%d%n", svr.getHost(), svr.getPort());
       
   178         svr.phaser.arriveAndAwaitAdvance(); // wait until the server has received its packet
   139 
   179 
   140         p = new DatagramPacket(msg, msg.length);
   180         p = new DatagramPacket(msg, msg.length);
   141         client.receive(p);
   181         client.receive(p);
   142 
   182 
   143         System.out.printf("echo received from: %s%n", p.getSocketAddress());
   183         System.out.printf("  echo received from: %s%n", p.getSocketAddress());
   144         if (msg[0] != 2) {
   184         if (msg[0] != 2) {
   145             throw new AssertionError("incorrect data received: expected: 2, actual: " + msg[0]);
   185             throw new AssertionError("incorrect data received: expected: 2, actual: " + msg[0]);
   146         }
   186         }
       
   187         svr.phaser.arriveAndAwaitAdvance(); // let the server null out its socket
   147 
   188 
   148         // Do NOT close the MulticastSocket; forget it
   189         // Do NOT close the MulticastSocket; forget it
   149 
   190 
   150         Object ref;
   191         Object ref;
   151         int loops = 20;
   192         int loops = 20;