1 /*
2  * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /*
25  * Tests that a thread blocked in DatagramSocket.receive
26  * throws a SocketException if the socket is asynchronously closed.
27  */
28 import java.net.*;
29 import java.util.concurrent.CountDownLatch;
30 import java.util.concurrent.atomic.AtomicBoolean;
31 
32 public class DatagramSocket_receive extends AsyncCloseTest implements Runnable {
33     private final DatagramSocket s;
34     private final int timeout;
35     private final CountDownLatch latch;
36     private final AtomicBoolean readyToClose = new AtomicBoolean(false);
37 
DatagramSocket_receive()38     public DatagramSocket_receive() throws SocketException {
39         this(0);
40     }
41 
DatagramSocket_receive(int timeout)42     public DatagramSocket_receive(int timeout) throws SocketException {
43         this.timeout = timeout;
44         latch = new CountDownLatch(1);
45         s = new DatagramSocket(0, InetAddress.getLoopbackAddress());
46     }
47 
description()48     public String description() {
49         String s = "DatagramSocket.receive(DatagramPacket)";
50         if (timeout > 0) {
51             s += " (timeout specified)";
52         }
53         return s;
54     }
55 
run()56     public void run() {
57         try {
58             byte b[] = new byte[1024];
59             DatagramPacket p  = new DatagramPacket(b, b.length);
60             if (timeout > 0) {
61                 s.setSoTimeout(timeout);
62             }
63             latch.countDown();
64             do {
65                 // if readyToClose is still false it means some other
66                 // process on the system attempted to send datagram packet:
67                 // just ignore it, and go back to accept again.
68                 s.receive(p);
69             } while (!readyToClose.get());
70             failed("DatagramSocket.receive(DatagramPacket) returned unexpectedly!!" + " - " + p.getAddress());
71         } catch (SocketException se) {
72             if (latch.getCount() != 1) {
73                 closed();
74             }
75         } catch (Exception e) {
76             failed(e.getMessage());
77         } finally {
78             if (latch.getCount() == 1) {
79                 latch.countDown();
80             }
81         }
82     }
83 
go()84     public AsyncCloseTest go() {
85         try {
86             Thread thr = new Thread(this);
87             thr.start();
88             latch.await();
89             Thread.sleep(5000); //sleep, so receive(DatagramPacket) can block
90             readyToClose.set(true);
91             s.close();
92             thr.join();
93 
94             if (isClosed()) {
95                 return passed();
96             } else {
97                 return failed("DatagramSocket.receive(DatagramPacket) wasn't preempted");
98             }
99         } catch (Exception x) {
100             failed(x.getMessage());
101             throw new RuntimeException(x);
102         }
103     }
104 }
105