RFR: 8245194: Unix domain socket channel implementation [v28]

Daniel Fuchs dfuchs at openjdk.java.net
Tue Oct 20 10:41:22 UTC 2020


On Mon, 19 Oct 2020 22:13:40 GMT, Michael McMahon <michaelm at openjdk.org> wrote:

>> Continuing this review as a PR on github with the comments below incorporated. I expect there will be a few more
>> iterations before integrating.
>> On 06/09/2020 19:47, Alan Bateman wrote:
>>> On 26/08/2020 15:24, Michael McMahon wrote:
>>>>
>>>> As I mentioned the other day, I wasn't able to use the suggested method on Windows which returns an absolute path. So,
>>>> I added a method to WindowsPath which returns the path in the expected UTF-8 encoding as a byte[]. Let me know what you
>>>> think of that.
>>>>
>>>> There is a fair bit of other refactoring and simplification done also. Next version is at:
>>>>
>>>> http://cr.openjdk.java.net/~michaelm/8245194/impl.webrev/webrev.9/
>>>>
>>> Adding a method to WindowsPath to encode the path using UTF-8 is okay but I don't think we should be caching it as the
>>> encoding for sun_path is an outlier on Windows. I'm also a bit dubious about encoding a relative path when the resolved
>>> path (before encoding) is > 247 chars. The documentation on the MS site isn't very completely and I think there are a
>>> number points that require clarification to fully understand how this will work with relative, directly relative and
>>> drive relative paths.
>>>
>> 
>> Maybe it would be better to just use the path returned from toString() and do the conversion to UTF-8 externally. That
>> would leave WindowsPath unchanged.
>>> In the same area, the new PathUtil is a bit inconsistent with the existing provider code. One suggestion is to add a
>>> method to AbstractFileSystemProvider instead. That is the base class the platform providers and would be a better place
>>> to get the file path in bytes.
>>>
>> 
>> Okay, I gave the method a name that is specific to Unix domain sockets because this UTF-8 strangeness is not likely to
>> be useful by other components.
>>> One other comment on the changes to the file system provider it should be okay to change UnixUserPrinipals ad its
>>> fromUid and fromGid method to be public. This would mean that the patch shouldn't need to add UnixUserGroup (the main
>>> issue is that class is that it means we end up with two classes with static factory methods doing the same thing).
>> 
>> Okay, that does simplify it a bit.
>> 
>> Thanks,
>> Michael.
>> 
>>> -Alan.
>>>
>>>
>>>
>>>
>>>
>>>
>
> Michael McMahon has updated the pull request incrementally with one additional commit since the last revision:
> 
>   final feedback from Alan

The tests mostly look good to me. There's a general cleanup needed to make sure channels get closed properly in case of
exception (that is - use try-with-resources whenever possible).

test/jdk/java/net/UnixDomainSocketAddress/AddressTest.java line 43:

> 41: public class AddressTest {
> 42:
> 43:     static UnixDomainSocketAddress addr;

This static seems to be unused?

test/jdk/java/net/UnixDomainSocketAddress/AddressTest.java line 29:

> 27:  * @compile ../../nio/file/spi/TestProvider.java AddressTest.java
> 28:  * @run testng/othervm AddressTest
> 29:  */

Could add `@summary` - IIUC this test checks that a Path that doesn't come from the build in filesystem is rejected by
`UnixDomainSocketAddress`?

test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/Launcher.java line 85:

> 83:         sc2.close();
> 84:         Files.delete(addr.getPath());
> 85:         ssc.close();

Should this use nested try-with-resources to close `ssc` and `sc2`?

test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/Launcher.java line 107:

> 105:         sc2.close();
> 106:         ssc.close();
> 107:         return sc1;

Here again nested try-with-resources could be used to close sc2 and ssc.

test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/Launcher.java line 136:

> 134:         ssc.close();
> 135:         InetSocketAddress isa = new InetSocketAddress(InetAddress.getLocalHost(), port);
> 136:         return SocketChannel.open(isa);

dito.

test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/Launcher.java line 144:

> 142:         var addr = ssc.getLocalAddress();
> 143:         launch(className, null, null, Util.getFD(ssc));
> 144:         ssc.close();

Use try-with-resource?

test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/Launcher.java line 170:

> 168:                                                             String[] options,
> 169:                                                             String... args)
> 170:             throws IOException {

Using try-with-resource or try-finally to make sure `dc` is closed properly should be envisaged.

test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/StateTest.java line 172:

> 170:         /*
> 171:          * Launch service with a SocketChannel (tcp nowait)
> 172:          */

try-with-resources or try-finally could be used in this file too to ensure that everything gets properly closed.

test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/UnixDomainChannelTest.java line 56:

> 54:                     ByteBuffer buf = ByteBuffer.wrap(result.getBytes(ISO_8859_1));
> 55:                     sc.write(buf);
> 56:                 }

Should the test fail if `channel` is not an instance of `SocketChannel`? Or at least print some kind of debug
information? Do we want to verify that it's a Unix Domain Socket Channel - e.g. by looking at the local address?
Same question for the server socket case below...

test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/UnixDomainChannelTest.java line 78:

> 76:     // Test with a named connected socket
> 77:     private static void test1() throws Exception {
> 78:         ServerSocketChannel listener = ServerSocketChannel.open(UNIX);

Maybe try with resources or try-finally could be used to ensure that all channels are closed.

test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/UnixSocketTest.java line 53:

> 51:     public static class Child2 {
> 52:         public static void main(String[] args) throws Exception {
> 53:             ServerSocketChannel server = (ServerSocketChannel)System.inheritedChannel();

Maybe use try-with-resources

test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/UnixSocketTest.java line 41:

> 39:     public static class Child1 {
> 40:         public static void main(String[] args) throws Exception {
> 41:             SocketChannel chan = (SocketChannel)System.inheritedChannel();

try-with-resources?

test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/UnixSocketTest.java line 68:

> 66:
> 67:     public static void main(String args[]) throws Exception {
> 68:         SocketChannel sc = Launcher.launchWithUnixSocketChannel("UnixSocketTest$Child1");

try-with-resources?

test/jdk/java/nio/channels/unixdomain/Bind.java line 118:

> 116:                 client.close();
> 117:             if (accept1 != null)
> 118:                 accept1.close();

Maybe each of these `close()` calls should be in its own try-catch.

test/jdk/java/nio/channels/unixdomain/Bind.java line 132:

> 130:     static void assertAddress(SocketAddress a, UnixDomainSocketAddress a1, String s) {
> 131:         if (!(a instanceof UnixDomainSocketAddress)) {
> 132:             throw new RuntimeException("wrong address type");

It would be useful to which wrong address type was observed.

test/jdk/java/nio/channels/unixdomain/Bind.java line 136:

> 134:         UnixDomainSocketAddress ua = (UnixDomainSocketAddress)a;
> 135:         if (!a.equals(a1))
> 136:             throw new RuntimeException("this is not the " + s + " address");

Could you consider turning this test into a `testng` test so that asssertEquals can be used?
Alternatively if you want to retain the ability to run the test as a standalone java program out of the repository then
consider modifying the assertXxxx methods so that the exception message prints both parts: `<what>` is not equal to
`<what>`

test/jdk/java/nio/channels/unixdomain/Bind.java line 140:

> 138:
> 139:     static void assertEquals(Object a, Object b) {
> 140:         if (!a.equals(b))

Should this call Objects.equals instead?

test/jdk/java/nio/channels/unixdomain/NonBlockingAccept.java line 61:

> 59:             System.out.println("The socketChannel is : expected Null " + socketChannel);
> 60:             // exception could be thrown otherwise
> 61:         }

Do we have/need a test that goes the whole way down? Register for OP_CONNECT with a selector and wait for the connect
to finish?

test/jdk/java/nio/channels/unixdomain/Security.java line 127:

> 125:         final UnixDomainSocketAddress saddr = UnixDomainSocketAddress.of(servername);
> 126:         final ServerSocketChannel server = ServerSocketChannel.open(UNIX);
> 127:         final SocketChannel client = SocketChannel.open(UNIX);

Maybe try-with-resources should be used and a finally too to ensure that the file is deleted...

test/jdk/java/nio/channels/unixdomain/Security.java line 145:

> 143:         final UnixDomainSocketAddress saddr = UnixDomainSocketAddress.of(servername);
> 144:         final ServerSocketChannel server = ServerSocketChannel.open(UNIX);
> 145:         final SocketChannel client = SocketChannel.open(UNIX);

Same remark as above

test/jdk/java/nio/channels/unixdomain/Security.java line 163:

> 161:         s1.bind(saddr);
> 162:         var s2 = ServerSocketChannel.open(UNIX);
> 163:         s2.bind(null);

same remark as above

test/jdk/java/nio/channels/unixdomain/SocketOptions.java line 59:

> 57:         s.bind(null);
> 58:         UnixDomainSocketAddress addr = (UnixDomainSocketAddress)s.getLocalAddress();
> 59:         SocketChannel c = SocketChannel.open(addr);

try-with-resources?

-------------

PR: https://git.openjdk.java.net/jdk/pull/52


More information about the hotspot-jfr-dev mailing list