RFR: 8245194: Unix domain socket channel implementation [v14]
Michael McMahon
michaelm at openjdk.java.net
Tue Oct 13 17:36:12 UTC 2020
On Mon, 12 Oct 2020 11:02:12 GMT, Michael McMahon <michaelm at openjdk.org> wrote:
>> Thanks again Alan. Assume where there is no comment from me below that suggestions are accepted:
>> I will push an update based on these changes soon.
>>
>> Michael.
>>
>>> _Mailing list message from [Alan Bateman](mailto:Alan.Bateman at oracle.com) on
>>> [nio-dev](mailto:nio-dev at openjdk.java.net):_
>>> On 04/10/2020 14:14, Michael McMahon wrote:
>>> Another round of comments, this time on v14.
>>>
>>> src/java.base/share/classes/java/net/StandardProtocolFamily.java
>>> - the enum constant is "UNIX" and might be better to put "Local" in
>>> parentheses rather than "Unix domain".
>>>
>>> src/java.base/share/classes/java/nio/channels/package-info.java
>>> - L260 ends with "family only", I think "only" can be dropped.
>>>
>>> src/java.base/share/classes/java/net/UnixDomainSocketAddress.java
>>> - left over "fix message" comments in constructor
>>> - a few formatting nits in the equals method due to a spurious space in
>>> the expression at L192, and missing a space at L194.
>>>
>>
>> I don't see a missing space at L194 ?
>>
>>> src/java.base/share/classes/sun/net/util/SocketExceptions.java
>>> - Can of(IOException e, SocketAddress addr) check enhancedExceptionText
>>> to avoid the ugly check in the ofXXX methods?
>>> - Can you explain the inconsistency in the null handling for the address
>>> types, maybe a left over from an early prototype?
>>>
>>
>> The null check was always there for Inet sockets. It is not required for Unix
>> but would be benign. So, the check can be promoted to the calling method.
>>
>>> src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java
>>> src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java
>>> - I think we need to change the class descriptions of both to start with
>>> "Base implementations ..."
>>> - We need to find a clean way to push the socket() method down to the
>>> InetXXXImpl classes as they are the only classes that should know about
>>> the socket adaptors.
>>
>> Only way to do this is to define yet another implXXX method (implSocket)
>> but I think it is worthwhile as neither the field nor the implementation
>> belong in the super class
>>
>>>
>>> src/java.base/share/classes/sun/nio/ch/UnixDomainServerSocketChannelImpl.java
>>> - implBind should not loop/retry when a local address is provided
>>
>> It actually catches the BindException and rethrows it when 'local != null, but maybe
>> the comment above the loop is confusing. I will reword it.
>>
>>> - what behavior is expected when getTempDir returns null?
>>
>> I was assuming that ${java.io.tmpdir} would always be defined, but I see
>> getTempDir() could be more robust in dealing with errors in the preceding
>> search steps. So, in the unlikely event that ${java.io.tmpdir} is not defined
>> null would be returned. I will change to throw a BindException in that case.
>>
>>> - Why doesn't this code use SecureRandom, as is done in the Windows
>>> Selector implementation.
>>
>> It does use SecureRandom but only uses the Random api.
>>
>>> - Can supportedOptions be changed to return
>>> Set.of(StandardSocketOptions.SO_RCVBUF)?
>>
>> I can simplify that code definitely, but I think for consistency it should
>> still return a static unmodifiable instance
>>
>>> - toString has a left over "TODO".
>>> - The message for the IOException in implBind should start with a
>>> capital to be consistent with the other exceptions thrown in this area
>>>
>>> src/java.base/share/classes/sun/nio/ch/UnixDomainSockets.java
>>> - The initializer sets the system property
>>> "jdk.nio.channels.unixdomain.maxnamelength". Looks like it's to help the
>>> tests so need to find another solution for the tests.
>>
>> Okay, the tests didn't really need this anyway
>>
>>> - checkCapability should be renamed to checkPermission as it does a
>>> security manager check. Would it more be consistent with existing code
>>> if changed to "if (sm != null) sm.checkPermission(...)"
>>> - Can inTempDirectory be removed as it doesn't seem to be used and
>>> raises several questions if it is needed.
>>> - getTempName should use the path separator rather than "/".? Also I
>>> don't think "nio" should be in the name.
>>> - Can the init method be removed, may be a left over from a previous
>>> iteration.
>>> - The left breaks in the initialization of UNNAMED and support seem
>>> unnecessary, maybe they were very long in previous iterations?
>>> - Several methods are public, is that intentional, or maybe a left over?
>>>
>>> src/java.base/unix/native/libnio/ch/UnixDomainSockets.c
>>> => Is the intention to put the NET_ functions into libnet or libnio? The
>>> function prototypes are declared in net_util.h but the functions have
>>> been compiled in libnio.
>>>
>>
>> They were probably in libnet originally, but makes more sense to be
>> in libnio. So, I will move the function prototypes to nio_util.h and rename
>> them to remove the NET_ prefix.
>>
>>> src/java.base/share/classes/sun/nio/ch/Net.java
>>> - spurious blank line, probably left over from a previous iteration.
>>>
>>> src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java
>>> src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java
>>> - getSunPathForSocketFile should not accept null, let
>>> to{Unix,Windows}Path handle it
>>>
>>> src/java.base/windows/classes/sun/nio/ch/PipeImpl.java
>>> src/java.base/windows/classes/sun/nio/ch/SinkChannelImpl.java
>>> src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java
>>> - The changes to PipeImpl look like they will set TCP_NODELAY for users
>>> of the Pipe API on older Windows releases. I think I would prefer to see
>>> a parameter on the PipeImpl constructor to indicate if there should
>>> buffered/nodelay or not. That way it will be clearer for the two usages
>>> of PipeImpl.
>>
>> Right, good point.
>>
>>> - The volatile noUnixDomainSockets does not need to be initialized to false.
>>>
>>> src/jdk.net/share/classes/jdk/net/UnixDomainPrincipal.java
>>> - if records are finalized in Java 16 then this may be a candidate to be
>>> a record
>>>
>>
>> Right. I don't think there is anything we can do further we can do right now
>> on this point, but if records make it, then it would be a simple API change to make.
>>
>>> test/jdk/java/nio/channels/etc/ProtocolFamilies.java
>>> - minor nit but the existing test uses "ssc", "sc", and "dc" so best to
>>> keep it consistent if you can.
>>>
>>> test/jdk/jdk/nio/Basic.java
>>> - can you change this to use
>>> Class.forName("sun.nio.ch.InetSocketChannelImpl"), that should be
>>> cleaner and void the retry and introducing getFD1.
>>>
>>
>> Good idea, but needs to be "sun.nio.ch.SocketChannelImpl" I think
>>
>>> I'm still working through the changes to the InheritedChannel
>>> implementation and all the changes/additions of tests so more comments
>>> soon on that aspect of the patch.
>>>
>>> -Alan.
>
>> _Mailing list message from [Alan Bateman](mailto:Alan.Bateman at oracle.com) on
>> [nio-dev](mailto:nio-dev at openjdk.java.net):_
>> I went through the latest patch, v18.
>>
>> I'm still a bit uncomfortable with splitting up SocketChannelImpl and
>> ServerSocketChannelImpl but okay with go along with this for now if we
>> can continue explore alternatives. Given that the InetXXX and UnixXXX
>> sub-classes aren't too big then one thing that we can try is just
>> special casing the protocol family in the 4-5 methods that are
>> different. In the mean-time, I think the abstract methods in
>> SocketChannelImpl and ServerSocketChannelImpl should have a clear method
>> description on what the implXXX method should. I would prefer the other
>> methods be changed to final so that it's clear that they cannot be
>> overridden. implSocket is new in v17 or v18 and I'd prefer if that were
>> abstract so it can be implemented in UnixXXX to throw UOE.
>>
>
> Okay, I'll take a look at pulling all the changes back into one SocketChannelImpl
> and ServerSocketChannelImpl.
>
>> I think the JFR events need another look. Are UnixSocketReadEvent and
>> UnixSocketWriteEvent really needed? SocketXXXEvent "address" is just a
>> String so it can be used for any address type, the port can be left as
>> 0. Part of this comment is wondering if a parallel set of events are
>> really needed. Part of it that I would prefer if the read/write methods
>> were final in SocketChannelImpl.
>>
>
> The existing socket read/write events include these fields:
>
> @Label("Remote Host")
> public String host;
>
> @Label("Remote Address")
> public String address;
>
> @Label("Remote Port")
> public int port;
>
> I guess, address could be used to encode a path name. port could just be set to -1
> and host could be hard coded to some string which indicates the event relates to
> a Unix domain socket. I was originally thinking "localhost" would be a good value,
> but it would need to be something more explicit than that, to clearly indicate the
> socket type, because remote addresses will often be empty path names.
>
> It could be a string like "Unix domain socket" or if a string with white-space embedded
> might cause a problem, then something like AF_UNIX:<path\> where path is the address (which
> might be empty)? Which wouldn't look great imo. I guess some guidance from JFR experts
> would help here ...
>
> All comments below look fine.
>
> Thanks
> Michael
>
>> You might want to take a pass over the files in the patch as several of
>> the new files have copyright dates starting 2012, 2019 and other years,
>> probably initially copied from other files.
>>
>> A few specific comments on v18:
>>
>> src/java.base/share/classes/sun/nio/ch/UnixDomainSocketChannelImpl.java
>> - supportedOptions doesn't need to wrap the unmodifable collection with
>> Collections.unmodifiableSet
>> - I think implBind should be re-worked so the local != null case is not
>> handled in the loop body. That will help future maintainers.
>>
>> src/java.base/windows/classes/sun/nio/ch/UnixDomainSocketsUtil.java
>> - I think we should look at adding JAVA_IO_TMPDIR to StaticProperty.
>>
>> src/java.base/unix/native/libnio/ch/UnixDomainSockets.c
>> - are the AIX specific includes really needed?
>> - can unixSocketAddressToSockaddr use if-then-else to avoid the goto.
>> - bind0 checks if the path is NULL, is this a left over?
>> - the declaration of accept0 is mis-aligned, might be left over from
>> refactoring
>>
>> src/java.base/unix/native/libnio/ch/InheritedChannel.c
>> - might be clearer if matchFamily is renamed to toInetFamily
>>
>> src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java
>> - peerAddress0 is replaced by peerAddressInet and peerAddressUnix0 which
>> looks a bit consistent, maybe rename those to inetPeerAddress0 and
>> unixPeerAddress0 ?
>>
>> src/java.base/windows/classes/sun/nio/ch/PipeImpl.java
>> - we've gone through a few iterations on this and only a few minor comments
>> - source/sink can be final and I assume no need to change their type
>> from SourceChannel/SinkChannel
>> - no need to initialize noUnixDomainSockets to false
>> - can the comments at L178-179 be turned into a method description.
>>
>> Can the tests for java.net.UnixDomainSocketAddress be moved to
>> jdk/test/java/net/UnixSocketAddress?
>>
>> Could test/jdk/java/nio/file/spi/TestProvider.java be used as
>> alternative provider in the test to avoid DummyPath?
>>
>> test/jdk/java/nio/channels/etc/ProtocolFamilies.java has been updated to
>> add "expectedFamily", is that used?
>>
>> test/jdk/java/nio/channels/unixdomain/WindowsDriver.java and
>> NonWindowsDriver.java
>> - are these needed now? Both of them run the same 5 tests and not clear
>> why these tests don't have their own @test tags.
>>
>> test/jdk/java/nio/channels/unixdomain/Security.java
>> - is there any reason why this test can't run with run
>> main/othervm/java.security.policy=java.policy1 -Djava.security.manager ?
>>
>> That's all I have from this pass over the changes.
>>
>> -Alan
So, I have done the refactoring and other work suggested and I think it was worthwhile. We're back to only two impl
classes now (from six). The JFR changes are simplified (at the cost of shoe-horning Unix domain addresses into the Inet
structure) but it's probably beneficial to have only one read and write event type for all sockets. When I went through
the comments below, there was one thing I missed in my reply yesterday. See below:
I will push these changes to the branch shortly.
> _Mailing list message from [Alan Bateman](mailto:Alan.Bateman at oracle.com) on
> [nio-dev](mailto:nio-dev at openjdk.java.net):_
> I went through the latest patch, v18.
>
> I'm still a bit uncomfortable with splitting up SocketChannelImpl and
> ServerSocketChannelImpl but okay with go along with this for now if we
> can continue explore alternatives. Given that the InetXXX and UnixXXX
> sub-classes aren't too big then one thing that we can try is just
> special casing the protocol family in the 4-5 methods that are
> different. In the mean-time, I think the abstract methods in
> SocketChannelImpl and ServerSocketChannelImpl should have a clear method
> description on what the implXXX method should. I would prefer the other
> methods be changed to final so that it's clear that they cannot be
> overridden. implSocket is new in v17 or v18 and I'd prefer if that were
> abstract so it can be implemented in UnixXXX to throw UOE.
>
> I think the JFR events need another look. Are UnixSocketReadEvent and
> UnixSocketWriteEvent really needed? SocketXXXEvent "address" is just a
> String so it can be used for any address type, the port can be left as
> 0. Part of this comment is wondering if a parallel set of events are
> really needed. Part of it that I would prefer if the read/write methods
> were final in SocketChannelImpl.
>
> You might want to take a pass over the files in the patch as several of
> the new files have copyright dates starting 2012, 2019 and other years,
> probably initially copied from other files.
>
> A few specific comments on v18:
>
> src/java.base/share/classes/sun/nio/ch/UnixDomainSocketChannelImpl.java
> - supportedOptions doesn't need to wrap the unmodifable collection with
> Collections.unmodifiableSet
> - I think implBind should be re-worked so the local != null case is not
> handled in the loop body. That will help future maintainers.
>
> src/java.base/windows/classes/sun/nio/ch/UnixDomainSocketsUtil.java
> - I think we should look at adding JAVA_IO_TMPDIR to StaticProperty.
>
> src/java.base/unix/native/libnio/ch/UnixDomainSockets.c
> - are the AIX specific includes really needed?
> - can unixSocketAddressToSockaddr use if-then-else to avoid the goto.
> - bind0 checks if the path is NULL, is this a left over?
> - the declaration of accept0 is mis-aligned, might be left over from
> refactoring
>
> src/java.base/unix/native/libnio/ch/InheritedChannel.c
> - might be clearer if matchFamily is renamed to toInetFamily
>
> src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java
> - peerAddress0 is replaced by peerAddressInet and peerAddressUnix0 which
> looks a bit consistent, maybe rename those to inetPeerAddress0 and
> unixPeerAddress0 ?
>
> src/java.base/windows/classes/sun/nio/ch/PipeImpl.java
> - we've gone through a few iterations on this and only a few minor comments
> - source/sink can be final and I assume no need to change their type
> from SourceChannel/SinkChannel
I added a package private method so SinkChannelImpl for accessing the channel. So, sink needs to be a SinkChannelImpl
at least. Also, the fields are not assigned in the constructor. So, don't think they can easily be made final.
> - no need to initialize noUnixDomainSockets to false
> - can the comments at L178-179 be turned into a method description.
>
> Can the tests for java.net.UnixDomainSocketAddress be moved to
> jdk/test/java/net/UnixSocketAddress?
>
> Could test/jdk/java/nio/file/spi/TestProvider.java be used as
> alternative provider in the test to avoid DummyPath?
>
> test/jdk/java/nio/channels/etc/ProtocolFamilies.java has been updated to
> add "expectedFamily", is that used?
>
> test/jdk/java/nio/channels/unixdomain/WindowsDriver.java and
> NonWindowsDriver.java
> - are these needed now? Both of them run the same 5 tests and not clear
> why these tests don't have their own @test tags.
>
> test/jdk/java/nio/channels/unixdomain/Security.java
> - is there any reason why this test can't run with run
> main/othervm/java.security.policy=java.policy1 -Djava.security.manager ?
>
> That's all I have from this pass over the changes.
>
> -Alan
-------------
PR: https://git.openjdk.java.net/jdk/pull/52
More information about the hotspot-jfr-dev
mailing list