调用 GetFileAttributesW() 删除管道

Calling GetFileAttributesW() removes a pipe

我从进程 A 创建了一个超时时间很长的管道 (//./pipe/mycoolpipe),

pipe = ::CreateNamedPipe(
        name_.c_str(),
        direction_,
        PIPE_TYPE_BYTE | PIPE_WAIT,
        1,
        ...,
        ...,
        PIPE_TIMEOUT,
    );

MS sysinternals pipelist.exe 正在枚举我的管道:

pipelist.exe | grep mycoolpipe
 //./pipe/mycoolpipe

然后我想从进程 B 读取文件属性:

::GetFileAttributesW(p.c_str()) // p == //./pipe/mycoolpipe

在调用 GetFileAttributesW 之后,管道消失了 - 什么?为什么?

注意:调试证明执行 GetFileAttributesW 会使管道消失 - pipelist.exe 在调用 GetFileAttributesW[=27= 后不再枚举它] 。不涉及超时。

GetFileAttributesW() 对非文件系统对象有未定义的行为,所以不要这样做。

http://permalink.gmane.org/gmane.os.cygwin.patches/1973

https://cygwin.com/ml/cygwin-patches/2004-q2/msg00193.html

But, while //server/pipe/name may be a UNC path, it is not a path to a file. And certain Win32 functions (including GetFileAttributes) do not work on those paths. When I say "do not work", I mean the Win32 SDK actually says not to call them on those paths, and when I do it on my XP Pro SP1 (with all updates), odd behavior ensues. This is undefined behavior. Sometimes I can see weird stuff at the filesystem level using SysInternals' FileMon.

GetFileAttributes behavior is not defined for pipe paths. So it cannot be called on those paths. I believe it returns -1 on my XP system - after it opens and closes the pipe, changing the semantics for the server! But there's no guarantee what it would return on other systems.

What we're up against here is a failing of the Win32 API:
1) GetFileAttributes cannot be called on a pipe path.
2) There is no function that can tell you that a path is a pipe path unless you actually open it and use GetFileType - which changes server semantics.
3) Therefore, you have to detect pipe paths and avoid calling GetFileAttributes.