1 /* 2 * Copyright (c) 2018, 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 /* @test 25 * @bug 8195160 26 * @summary Test asynchronous close during a blocking write 27 * @requires (os.family == "linux") 28 * @library .. /test/lib 29 * @build RsocketTest 30 * @run main/othervm CloseDuringWrite 31 * @key randomness 32 */ 33 34 import java.io.Closeable; 35 import java.io.IOException; 36 import java.net.InetAddress; 37 import java.net.InetSocketAddress; 38 import java.net.StandardProtocolFamily; 39 import java.net.SocketAddress; 40 import java.nio.ByteBuffer; 41 import java.nio.channels.ClosedChannelException; 42 import java.nio.channels.ServerSocketChannel; 43 import java.nio.channels.SocketChannel; 44 import java.util.concurrent.Callable; 45 import java.util.concurrent.Executors; 46 import java.util.concurrent.Future; 47 import java.util.concurrent.ScheduledExecutorService; 48 import java.util.concurrent.TimeUnit; 49 import java.util.Random; 50 import jdk.net.RdmaSockets; 51 52 import jtreg.SkippedException; 53 54 public class CloseDuringWrite { 55 56 static final Random rand = new Random(); 57 static ServerSocketChannel ssc; 58 static SocketChannel source; 59 static SocketAddress sa; 60 61 /** 62 * A task that closes a Closeable 63 */ 64 static class Closer implements Callable<Void> { 65 final Closeable c; 66 Closer(Closeable c) { 67 this.c = c; 68 } 69 public Void call() throws IOException { 70 c.close(); 71 return null; 72 } 73 } 74 75 public static void main(String[] args) throws Exception { 76 if (!RsocketTest.isRsocketAvailable()) 77 throw new SkippedException("rsocket is not available"); 78 79 ScheduledExecutorService pool = Executors.newSingleThreadScheduledExecutor(); 80 try { 81 try { 82 ssc = RdmaSockets.openServerSocketChannel( 83 StandardProtocolFamily.INET); 84 InetAddress lh = InetAddress.getLocalHost(); 85 ssc.bind(new InetSocketAddress(lh, 0)); 86 int port = ssc.socket().getLocalPort(); 87 sa = new InetSocketAddress(lh, port); 88 89 ByteBuffer bb = ByteBuffer.allocate(2 * 1024 * 1024); 90 91 for (int i = 0; i < 20; i++) { 92 try { 93 source = RdmaSockets.openSocketChannel( 94 StandardProtocolFamily.INET); 95 Runnable runnable = new Runnable() { 96 @Override 97 public void run() { 98 try { 99 source.connect(sa); 100 } catch (Exception e) { 101 e.printStackTrace(); 102 throw new RuntimeException("Test Failed"); 103 } 104 } 105 }; 106 107 Thread t = new Thread(runnable); 108 t.start(); 109 SocketChannel sink = ssc.accept(); 110 // schedule channel to be closed 111 Closer c = new Closer(source); 112 int when = 1000 + rand.nextInt(2000); 113 Future<Void> result = pool.schedule(c, when, TimeUnit.MILLISECONDS); 114 115 // the write should either succeed or else throw a 116 // ClosedChannelException (more likely an 117 // AsynchronousCloseException) 118 try { 119 for (;;) { 120 int limit = rand.nextInt(bb.capacity()); 121 bb.position(0); 122 bb.limit(limit); 123 int n = source.write(bb); 124 System.out.format("wrote %d, expected %d%n", n, limit); 125 } 126 } catch (ClosedChannelException expected) { 127 System.out.println(expected + " (expected)"); 128 } finally { 129 result.get(); 130 } 131 } catch (Exception e) { 132 e.printStackTrace(); 133 throw new RuntimeException("Test Failed"); 134 } 135 } 136 } catch (Exception e) { 137 e.printStackTrace(); 138 throw new RuntimeException("Test Failed"); 139 } 140 } finally { 141 pool.shutdown(); 142 } 143 } 144 }