From 73e6667cd7fb5aa43771868f738dd511a6f7d97c Mon Sep 17 00:00:00 2001 From: alanb Date: Thu, 8 Feb 2018 10:55:21 +0000 Subject: [PATCH] 8196956: (ch) More channels cleanup 8231795: Enhance datagram socket support Reviewed-by: rriggs, prappo, bpb --- .../java/nio/channels/SelectableChannel.java | 2 +- .../spi/AbstractSelectableChannel.java | 34 ++++++++++------- .../sun/nio/ch/DatagramChannelImpl.java | 26 ++++++++----- .../sun/nio/ch/DatagramSocketAdaptor.java | 30 ++++++++++----- .../sun/nio/ch/ServerSocketAdaptor.java | 32 +++++++++++----- .../sun/nio/ch/ServerSocketChannelImpl.java | 5 +-- .../classes/sun/nio/ch/SocketAdaptor.java | 37 +++++++++++++------ .../classes/sun/nio/ch/SocketChannelImpl.java | 3 -- 8 files changed, 106 insertions(+), 63 deletions(-) diff --git a/src/share/classes/java/nio/channels/SelectableChannel.java b/src/share/classes/java/nio/channels/SelectableChannel.java index 997d5c5ec..c7d75967a 100644 --- a/src/share/classes/java/nio/channels/SelectableChannel.java +++ b/src/share/classes/java/nio/channels/SelectableChannel.java @@ -121,7 +121,7 @@ public abstract class SelectableChannel // keySet, may be empty but is never null, typ. a tiny array // boolean isRegistered, protected by key set // regLock, lock object to prevent duplicate registrations - // boolean isBlocking, protected by regLock + // blocking mode, protected by regLock /** * Tells whether or not this channel is currently registered with any diff --git a/src/share/classes/java/nio/channels/spi/AbstractSelectableChannel.java b/src/share/classes/java/nio/channels/spi/AbstractSelectableChannel.java index 0de212d2d..d5b3ce8bb 100644 --- a/src/share/classes/java/nio/channels/spi/AbstractSelectableChannel.java +++ b/src/share/classes/java/nio/channels/spi/AbstractSelectableChannel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2018, 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 @@ -26,7 +26,14 @@ package java.nio.channels.spi; import java.io.IOException; -import java.nio.channels.*; +import java.nio.channels.CancelledKeyException; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.ClosedSelectorException; +import java.nio.channels.IllegalBlockingModeException; +import java.nio.channels.IllegalSelectorException; +import java.nio.channels.SelectableChannel; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; /** @@ -67,8 +74,8 @@ public abstract class AbstractSelectableChannel // Lock for registration and configureBlocking operations private final Object regLock = new Object(); - // Blocking mode, protected by regLock - boolean blocking = true; + // True when non-blocking, need regLock to change; + private volatile boolean nonBlocking; /** * Initializes a new instance of this class. @@ -197,7 +204,7 @@ public abstract class AbstractSelectableChannel throw new ClosedChannelException(); if ((ops & ~validOps()) != 0) throw new IllegalArgumentException(); - if (blocking) + if (isBlocking()) throw new IllegalBlockingModeException(); SelectionKey k = findKey(sel); if (k != null) { @@ -264,9 +271,7 @@ public abstract class AbstractSelectableChannel // -- Blocking -- public final boolean isBlocking() { - synchronized (regLock) { - return blocking; - } + return !nonBlocking; } public final Object blockingLock() { @@ -287,12 +292,13 @@ public abstract class AbstractSelectableChannel synchronized (regLock) { if (!isOpen()) throw new ClosedChannelException(); - if (blocking == block) - return this; - if (block && haveValidKeys()) - throw new IllegalBlockingModeException(); - implConfigureBlocking(block); - blocking = block; + boolean blocking = !nonBlocking; + if (block != blocking) { + if (block && haveValidKeys()) + throw new IllegalBlockingModeException(); + implConfigureBlocking(block); + nonBlocking = !block; + } } return this; } diff --git a/src/share/classes/sun/nio/ch/DatagramChannelImpl.java b/src/share/classes/sun/nio/ch/DatagramChannelImpl.java index 53e84d434..b91093f49 100644 --- a/src/share/classes/sun/nio/ch/DatagramChannelImpl.java +++ b/src/share/classes/sun/nio/ch/DatagramChannelImpl.java @@ -49,9 +49,6 @@ class DatagramChannelImpl // Our file descriptor private final FileDescriptor fd; - - // fd value needed for dev/poll. This value will remain valid - // even after the value in the file descriptor object has been set to -1 private final int fdVal; // The protocol family of the socket @@ -103,7 +100,6 @@ class DatagramChannelImpl // -- End of fields protected by stateLock - public DatagramChannelImpl(SelectorProvider sp) throws IOException { @@ -138,16 +134,27 @@ class DatagramChannelImpl throw new UnsupportedOperationException("IPv6 not available"); } } - this.family = family; - this.fd = Net.socket(family, false); - this.fdVal = IOUtil.fdVal(fd); - this.state = ST_UNCONNECTED; + + ResourceManager.beforeUdpCreate(); + try { + this.family = family; + this.fd = Net.socket(family, false); + this.fdVal = IOUtil.fdVal(fd); + this.state = ST_UNCONNECTED; + } catch (IOException ioe) { + ResourceManager.afterUdpClose(); + throw ioe; + } } public DatagramChannelImpl(SelectorProvider sp, FileDescriptor fd) throws IOException { super(sp); + + // increment UDP count to match decrement when closing + ResourceManager.beforeUdpCreate(); + this.family = Net.isIPv6Available() ? StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; this.fd = fd; @@ -742,10 +749,9 @@ class DatagramChannelImpl localAddress = Net.localAddress(fd); // flush any packets already received. - boolean blocking = false; synchronized (blockingLock()) { + boolean blocking = isBlocking(); try { - blocking = isBlocking(); // remainder of each packet thrown away ByteBuffer tmpBuf = ByteBuffer.allocate(1); if (blocking) { diff --git a/src/share/classes/sun/nio/ch/DatagramSocketAdaptor.java b/src/share/classes/sun/nio/ch/DatagramSocketAdaptor.java index fe2ed2300..838a02d03 100644 --- a/src/share/classes/sun/nio/ch/DatagramSocketAdaptor.java +++ b/src/share/classes/sun/nio/ch/DatagramSocketAdaptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2018, 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 @@ -25,10 +25,22 @@ package sun.nio.ch; -import java.io.*; -import java.net.*; -import java.nio.*; -import java.nio.channels.*; +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.DatagramSocketImpl; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.NetworkInterface; +import java.net.SocketAddress; +import java.net.SocketException; +import java.net.SocketOption; +import java.net.SocketTimeoutException; +import java.net.StandardSocketOptions; +import java.nio.ByteBuffer; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.DatagramChannel; +import java.nio.channels.IllegalBlockingModeException; // Make a datagram-socket channel look like a datagram socket. @@ -178,7 +190,6 @@ public class DatagramSocketAdaptor dc.configureBlocking(false); try { - int n; SocketAddress sender; if ((sender = dc.receive(bb)) != null) return sender; @@ -188,19 +199,18 @@ public class DatagramSocketAdaptor throw new ClosedChannelException(); long st = System.currentTimeMillis(); int result = dc.poll(Net.POLLIN, to); - if (result > 0 && - ((result & Net.POLLIN) != 0)) { + if (result > 0 && ((result & Net.POLLIN) != 0)) { if ((sender = dc.receive(bb)) != null) return sender; } to -= System.currentTimeMillis() - st; if (to <= 0) throw new SocketTimeoutException(); - } } finally { - if (dc.isOpen()) + try { dc.configureBlocking(true); + } catch (ClosedChannelException e) { } } } diff --git a/src/share/classes/sun/nio/ch/ServerSocketAdaptor.java b/src/share/classes/sun/nio/ch/ServerSocketAdaptor.java index 4357ffc4e..63574acc7 100644 --- a/src/share/classes/sun/nio/ch/ServerSocketAdaptor.java +++ b/src/share/classes/sun/nio/ch/ServerSocketAdaptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2018, 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 @@ -25,9 +25,20 @@ package sun.nio.ch; -import java.io.*; -import java.net.*; -import java.nio.channels.*; +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.SocketException; +import java.net.SocketTimeoutException; +import java.net.StandardSocketOptions; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.IllegalBlockingModeException; +import java.nio.channels.NotYetBoundException; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; // Make a server-socket channel look like a server socket. @@ -37,7 +48,7 @@ import java.nio.channels.*; // class. // -public class ServerSocketAdaptor // package-private +class ServerSocketAdaptor // package-private extends ServerSocket { @@ -97,12 +108,16 @@ public class ServerSocketAdaptor // package-private throw new IllegalBlockingModeException(); try { if (timeout == 0) { + // for compatibility reasons: accept connection if available + // when configured non-blocking SocketChannel sc = ssc.accept(); if (sc == null && !ssc.isBlocking()) throw new IllegalBlockingModeException(); return sc.socket(); } + if (!ssc.isBlocking()) + throw new IllegalBlockingModeException(); ssc.configureBlocking(false); try { SocketChannel sc; @@ -121,10 +136,10 @@ public class ServerSocketAdaptor // package-private throw new SocketTimeoutException(); } } finally { - if (ssc.isOpen()) + try { ssc.configureBlocking(true); + } catch (ClosedChannelException e) { } } - } catch (Exception x) { Net.translateException(x); assert false; @@ -178,8 +193,7 @@ public class ServerSocketAdaptor // package-private if (!isBound()) return "ServerSocket[unbound]"; return "ServerSocket[addr=" + getInetAddress() + - // ",port=" + getPort() + - ",localport=" + getLocalPort() + "]"; + ",localport=" + getLocalPort() + "]"; } public void setReceiveBufferSize(int size) throws SocketException { diff --git a/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java b/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java index ee5ff7675..563f948cf 100644 --- a/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java +++ b/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java @@ -48,10 +48,7 @@ class ServerSocketChannelImpl // Our file descriptor private final FileDescriptor fd; - - // fd value needed for dev/poll. This value will remain valid - // even after the value in the file descriptor object has been set to -1 - private int fdVal; + private final int fdVal; // ID of native thread currently blocked in this channel, for signalling private volatile long thread = 0; diff --git a/src/share/classes/sun/nio/ch/SocketAdaptor.java b/src/share/classes/sun/nio/ch/SocketAdaptor.java index d115b7aaf..c128dc53c 100644 --- a/src/share/classes/sun/nio/ch/SocketAdaptor.java +++ b/src/share/classes/sun/nio/ch/SocketAdaptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2018, 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 @@ -25,11 +25,23 @@ package sun.nio.ch; -import java.io.*; -import java.lang.ref.*; -import java.net.*; -import java.nio.*; -import java.nio.channels.*; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.SocketException; +import java.net.SocketImpl; +import java.net.SocketOption; +import java.net.SocketTimeoutException; +import java.net.StandardSocketOptions; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.IllegalBlockingModeException; +import java.nio.channels.SocketChannel; import java.security.AccessController; import java.security.PrivilegedExceptionAction; import java.util.*; @@ -47,7 +59,7 @@ import java.util.*; // java.net.Socket so as to simplify tracking future changes to that class. // -public class SocketAdaptor +class SocketAdaptor extends Socket { @@ -91,7 +103,6 @@ public class SocketAdaptor throw new IllegalBlockingModeException(); try { - if (timeout == 0) { sc.connect(remote); return; @@ -119,8 +130,9 @@ public class SocketAdaptor } } } finally { - if (sc.isOpen()) + try { sc.configureBlocking(true); + } catch (ClosedChannelException e) { } } } catch (Exception x) { @@ -188,10 +200,11 @@ public class SocketAdaptor synchronized (sc.blockingLock()) { if (!sc.isBlocking()) throw new IllegalBlockingModeException(); + if (timeout == 0) return sc.read(bb); - sc.configureBlocking(false); + sc.configureBlocking(false); try { int n; if ((n = sc.read(bb)) != 0) @@ -211,10 +224,10 @@ public class SocketAdaptor throw new SocketTimeoutException(); } } finally { - if (sc.isOpen()) + try { sc.configureBlocking(true); + } catch (ClosedChannelException e) { } } - } } } diff --git a/src/share/classes/sun/nio/ch/SocketChannelImpl.java b/src/share/classes/sun/nio/ch/SocketChannelImpl.java index 7b694efe6..164a16566 100644 --- a/src/share/classes/sun/nio/ch/SocketChannelImpl.java +++ b/src/share/classes/sun/nio/ch/SocketChannelImpl.java @@ -50,9 +50,6 @@ class SocketChannelImpl // Our file descriptor object private final FileDescriptor fd; - - // fd value needed for dev/poll. This value will remain valid - // even after the value in the file descriptor object has been set to -1 private final int fdVal; // IDs of native threads doing reads and writes, for signalling -- GitLab