JDK-8252971 : WindowsFileAttributes does not know about Unix domain sockets
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_10
  • CPU: x86_64
  • Submitted: 2020-09-09
  • Updated: 2021-03-01
  • Resolved: 2021-02-12
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 16 JDK 17
16.0.1Fixed 17 b10Fixed
Description
If you create a Unix domain socket on Windows ( 2019 server) and try to get its file attributes with:
  Files.readAttributes(p, BasicFileAttributes.class)
this will fail with:

$ java Foo
foo.sock
Server: local address = foo.sock
Exception in thread "main" java.nio.file.FileSystemException: foo.sock: The file cannot be accessed by the
 system
        at java.base/sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:92)
        at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:103)
        at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:108)
        at java.base/sun.nio.fs.WindowsFileAttributeViews$Basic.readAttributes(WindowsFileAttributeViews.j
ava:53)
        at java.base/sun.nio.fs.WindowsFileAttributeViews$Basic.readAttributes(WindowsFileAttributeViews.j
ava:38)
        at java.base/sun.nio.fs.WindowsFileSystemProvider.readAttributes(WindowsFileSystemProvider.java:19
9)
        at java.base/java.nio.file.Files.readAttributes(Files.java:1843)
        at Foo.main(Foo.java:18)

A test program to generate this is as follows. However, this depends on JEP380 which has not been integrated into 16 yet. A native executable could show it also.

$ cat Foo.java
import java.io.*;
import java.net.*;
import java.util.*;
import java.nio.*;
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.nio.channels.*;

public class Foo {

    public static void main(String[] args) throws Exception {
        var server = ServerSocketChannel.open(StandardProtocolFamily.UNIX);
        String s = new String("foo.sock");
        System.out.println(s);
        Path p = Path.of(s);
        server.bind(UnixDomainSocketAddress.of(p));
        System.out.println("Server: local address = " + server.getLocalAddress());
        BasicFileAttributes attrs = Files.readAttributes(p, BasicFileAttributes.class);
    }
}

The problem relates to the implementation of Unix domain sockets on Windows as NTFS reparse points, which typically require special handling in user code.

Incidentally, Cygwin has the same problem and at times is unable to delete the socket files. So "rm foo.sock" typically fails with a permission error. This can be worked around by doing "cmd /c del foo.sock" from a Cygwin command prompt.
Comments
Fix Request We would like to backport this from 17 to 16 update 2. Unfortunately, the initial version of JEP-380 in 16 has only limited support on Windows. This fix makes it available on all versions of Windows that has underlying OS support. The patch applies cleanly and is currently being tested tier1, tier2 in mach5 at (https://mach5.us.oracle.com/mdash/jobs/mimcmah-jdk16u-20210223-1852-18602381)
23-02-2021

Changeset: 9ffabf30 Author: Michael McMahon <michaelm@openjdk.org> Date: 2021-02-12 13:08:08 +0000 URL: https://git.openjdk.java.net/jdk/commit/9ffabf30
12-02-2021

It now appears this issue affects all versions of Windows 2019 Server and all versions of Windows 10 except for 1903 and 1909. I have a patch for 17 ready to review, and hopefully it will be back ported to the first update of 16.
31-01-2021

A better workaround for when Cygwin "rm -rf dir" fails, due to the related Cygwin issue, is: cmd /c "rd /s /q dir" from Cygwin bash or rd /s /q dir from a Windows command prompt.
25-09-2020

The cause of this is that when opening a Unix domain socket (to get its attributes) with CreateFile you must set the FILE_FLAG_OPEN_REPARSE_POINT flag because it is a reparse point. Up to now, we only set this flag when the user API call has selected the "don't follow symbolic links" option because there has been only one type of reparse point (symbolic links). There are now two independent reasons for setting the flag. The problem with having to set it when opening a socket is that while we know whether the object is a reparse point (from GetFileAttributesEx), we can't know the type of reparse point until we open it. If the object is a symbolic link, we have to observe the original "don't follow links" logic (ie open the link target, or the link itself), but if the object is a socket then we must always open the object itself. The solution to this is to open the file as we do currently, and if it fails (in the case when we know it is a reparse point, and followLinks is true) then retry with FILE_FLAG_OPEN_REPARSE_POINT set. We can then retrieve the file attributes and verify that the object is a socket. If not, the original exception can be re-thrown.
25-09-2020

Will address this after JEP-380 is integrated.
09-09-2020