[Windows] Delete UNIX domain socket paths that NIO created - #3709
[Windows] Delete UNIX domain socket paths that NIO created#3709jakepetroules wants to merge 1 commit into
Conversation
| // A UNIX domain socket is a reparse point in the file system, so it *is* a disk object; | ||
| // anything else (a pipe, a character device) cannot be one. Which kind of disk object this | ||
| // is gets settled by the reparse tag checked below. |
There was a problem hiding this comment.
Am I missing something here? Why is this suddenly about UNIX?
There was a problem hiding this comment.
This is inside cleanupUnixDomainSocket(atPath:). The hunk doesn't show the signature, which is a bit further up.
On Windows a bound AF_UNIX path is a reparse point on disk, so GetFileType returns FILE_TYPE_DISK for it. That's the case the old check rejected. I trimmed the comment to one line.
Three things stopped `cleanupUnixDomainSocket` from ever removing a socket path on Windows. A path that does not exist threw `IOError(windows: EBADF)`, mixing an `errno` value into the Windows error domain, where the POSIX implementation treats a missing path as already cleaned up and returns successfully. The type check then rejected `FILE_TYPE_DISK`. A UNIX domain socket on Windows is a reparse point in the file system, so that is exactly what `GetFileType` reports for one, meaning the check rejected the case the function exists to handle. What distinguishes a socket from an ordinary file is the reparse tag, which the code already inspects further down, so require a disk object rather than reject one. The old `guard` also combined the type with the error state, which is how a rejected path came to be reported as `IOError(windows: 0)`, rendering as "The operation completed successfully"; check the two separately, following `GetFileType`'s contract that failure is `FILE_TYPE_UNKNOWN` together with an error being set. Finally the handle was opened with `GENERIC_READ` alone, so the `SetFileInformationByHandle` that removes the path failed with access denied. Ask for `DELETE` as well.
777f9ca to
2a7f483
Compare
|
No, it doesn't enable any tests, and it removes no skips. The Windows UNIX domain socket tests stay skipped for a separate reason: they bind with What this fix unblocks is UNIX domain socket channel pairs in the test helpers. On a follow-up branch that enables them, |
Motivation:
cleanupUnixDomainSocketcould never delete a socket path on Windows. There were three reasons.A path that does not exist. It threw
IOError(windows: EBADF), which puts an errno value into the Windows error domain. The POSIX code treats a missing path as already clean and returns.The file type check was inverted. It rejected
FILE_TYPE_DISK. On Windows a UNIX domain socket is a reparse point in the file system, soGetFileTypereports exactly that. The check rejected the case the function exists for. The reparse tag, which the same function checks a few lines later, is what tells a socket from a normal file. The oldguardalso mixed the file type and the error state in one condition, so a rejected path was reported asIOError(windows: 0). That reads as "The operation completed successfully".The handle had no delete access. It was opened with
GENERIC_READonly, soSetFileInformationByHandlefailed with access denied.Measured on a Windows ARM64 machine. The test binds an
AF_UNIXsocket, then asks NIO to clean the path up:existsAfterBind=falseisFileManagerfollowing the reparse point.GetFileAttributesExWreports0x420, which includesFILE_ATTRIBUTE_REPARSE_POINT.Modifications:
ERROR_FILE_NOT_FOUNDandERROR_PATH_NOT_FOUNDas already clean, and return. This matches how POSIX handlesENOENT.FILE_TYPE_DISKinstead of rejecting it. Check theGetFileTypefailure case separately, following its contract: failure isFILE_TYPE_UNKNOWNand an error is set. A path that exists but is not a socket now reportsUnixDomainSocketPathWrongType, as on POSIX.DELETEaccess as well.This file is Windows-only.
Result:
NIO can now rebind a UNIX domain socket path that it used before on Windows. It also reports the same errors as the POSIX code for a missing path and for a wrong file type.
This is also what makes UNIX domain socket channel pairs usable in the tests. On a branch that enables them,
StreamChannelTestgoes from 1 passing test to 17.Tested on a Windows ARM64 machine (Swift 6.3.2): builds on its own, and part of a larger branch where a full
swift testpasses (2360 tests, 0 failures).