8071599: (so) Socket adapter sendUrgentData throws IllegalBlockingMode when channel configured non-blocking
Summary: Remove restriction to blocking case
Reviewed-by: alanb, chegar
--- a/jdk/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java Fri Feb 27 18:12:07 2015 +0000
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java Fri Feb 27 14:36:03 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -321,12 +321,9 @@
}
public void sendUrgentData(int data) throws IOException {
- synchronized (sc.blockingLock()) {
- if (!sc.isBlocking())
- throw new IllegalBlockingModeException();
- int n = sc.sendOutOfBandData((byte)data);
- assert n == 1;
- }
+ int n = sc.sendOutOfBandData((byte) data);
+ if (n == 0)
+ throw new IOException("Socket buffer full");
}
public void setOOBInline(boolean on) throws SocketException {
--- a/jdk/test/java/nio/channels/SocketChannel/OutOfBand.java Fri Feb 27 18:12:07 2015 +0000
+++ b/jdk/test/java/nio/channels/SocketChannel/OutOfBand.java Fri Feb 27 14:36:03 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -58,8 +58,6 @@
test1(sc1, sc2);
test2(sc1, sc2);
test3(sc1, sc2);
- test4(sc1);
-
} finally {
if (sc1 != null) sc1.close();
if (sc2 != null) sc2.close();
@@ -175,17 +173,4 @@
thr.join();
}
-
- static void test4(SocketChannel sc) throws IOException {
- boolean blocking = sc.isBlocking();
- sc.configureBlocking(false);
- try {
- sc.socket().sendUrgentData(0);
- throw new RuntimeException("IllegalBlockingModeException expected");
- } catch (IllegalBlockingModeException x) {
- // expected
- } finally {
- sc.configureBlocking(blocking);
- }
- }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/channels/SocketChannel/SendUrgentData.java Fri Feb 27 14:36:03 2015 -0800
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8071599
+ * @run main/othervm SendUrgentData
+ * @run main/othervm SendUrgentData -inline
+ * @summary Test sending of urgent data.
+ */
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+
+public class SendUrgentData {
+
+ /**
+ * The arguments may be one of the following:
+ * <ol>
+ * <li>-server</li>
+ * <li>-client host port [-inline]</li>
+ * <li>[-inline]</li>
+ * </ol>
+ * The first option creates a standalone server, the second a standalone
+ * client, and the third a self-contained server-client pair on the
+ * local host.
+ *
+ * @param args
+ * @throws Exception
+ */
+ public static void main(String[] args) throws Exception {
+
+ ServerSocketChannelThread serverThread
+ = new ServerSocketChannelThread("SendUrgentDataServer");
+ serverThread.start();
+ boolean b = serverThread.isAlive();
+
+ String host = null;
+ int port = 0;
+ boolean inline = false;
+ if (args.length > 0 && args[0].equals("-server")) {
+ System.out.println(serverThread.getAddress());
+ Thread.currentThread().suspend();
+ } else {
+ if (args.length > 0 && args[0].equals("-client")) {
+ host = args[1];
+ port = Integer.parseInt(args[2]);
+ if (args.length > 3) {
+ inline = args[2].equals("-inline");
+ }
+ } else {
+ host = "localhost";
+ port = serverThread.getAddress().getPort();
+ if (args.length > 0) {
+ inline = args[0].equals("-inline");
+ }
+ }
+ }
+
+ System.out.println("OOB Inline : "+inline);
+
+ SocketAddress sa = new InetSocketAddress(host, port);
+
+ try (SocketChannel sc = SocketChannel.open(sa)) {
+ sc.configureBlocking(false);
+ sc.socket().setOOBInline(inline);
+
+ sc.socket().sendUrgentData(0);
+ System.out.println("wrote 1 OOB byte");
+
+ ByteBuffer bb = ByteBuffer.wrap(new byte[100 * 1000]);
+
+ int blocked = 0;
+ long total = 0;
+
+ int n;
+ do {
+ n = sc.write(bb);
+ if (n == 0) {
+ System.out.println("blocked, wrote " + total + " so far");
+ if (++blocked == 10) {
+ break;
+ }
+ Thread.sleep(100);
+ } else {
+ total += n;
+ bb.rewind();
+ }
+ } while (n > 0);
+
+ long attempted = 0;
+ while (attempted < total) {
+ bb.rewind();
+ n = sc.write(bb);
+ System.out.println("wrote " + n + " normal bytes");
+ attempted += bb.capacity();
+
+ String osName = System.getProperty("os.name").toLowerCase();
+
+ try {
+ sc.socket().sendUrgentData(0);
+ } catch (IOException ex) {
+ if (osName.contains("linux")) {
+ if (!ex.getMessage().contains("Socket buffer full")) {
+ throw new RuntimeException("Unexpected message", ex);
+ }
+ } else if (osName.contains("os x") || osName.contains("mac")) {
+ if (!ex.getMessage().equals("No buffer space available")) {
+ throw new RuntimeException("Unexpected message", ex);
+ }
+ } else if (osName.contains("windows")) {
+ if (!(ex instanceof SocketException)) {
+ throw new RuntimeException("Unexpected exception", ex);
+ } else if (!ex.getMessage().contains("Resource temporarily unavailable")) {
+ throw new RuntimeException("Unexpected message", ex);
+ }
+ } else {
+ throw new RuntimeException("Unexpected IOException", ex);
+ }
+ }
+
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException ex) {
+ // don't want to fail on this so just print trace and break
+ ex.printStackTrace();
+ break;
+ }
+ }
+ } finally {
+ serverThread.close();
+ }
+ }
+
+ static class ServerSocketChannelThread extends Thread {
+
+ private ServerSocketChannel ssc;
+
+ private ServerSocketChannelThread(String name) {
+ super(name);
+ try {
+ ssc = ServerSocketChannel.open();
+ ssc.bind(new InetSocketAddress((0)));
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ public void run() {
+ while (ssc.isOpen()) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ try {
+ ssc.close();
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ System.out.println("ServerSocketChannelThread exiting ...");
+ }
+
+ public InetSocketAddress getAddress() throws IOException {
+ if (ssc == null) {
+ throw new IllegalStateException("ServerSocketChannel not created");
+ }
+
+ return (InetSocketAddress) ssc.getLocalAddress();
+ }
+
+ public void close() {
+ try {
+ ssc.close();
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ }
+}