命名管道:ReadFile after ConnectNamedPipe return ERROR_BROKEN_PIPE

Named pipe: ReadFile after ConnectNamedPipe return ERROR_BROKEN_PIPE

我重新激活了我确定在几个月前使用过的代码。它让我发疯,但它不再是了。我在其他问题中找不到答案。

在服务器端,我使用

创建了一个管道
#define MAX_MESSAGE_LENGTH 1024
SECURITY_ATTRIBUTES sa;
SECURITY_DESCRIPTOR sd;
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, static_cast<PACL>(0), FALSE);

sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = FALSE;

auto pipe_name = _T("\\.\pipe\") + _serviceName;

HANDLE pipe = CreateNamedPipe(
    pipe_name.c_str(),
    PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE,
    PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
    1, 
    MAX_MESSAGE_LENGTH, MAX_MESSAGE_LENGTH, // buffer lengths (advisory)
    0, // default timeout of 50ms when WaitNamedPipe uses NMPWAIT_USE_DEFAULT_WAIT
    &sa));

然后一个线程等待 ConnectNamedPipe 传入的客户端。 ConnectNamedPipe 阻塞,直到客户端连接

HANDLE pipe = CreateFile(
    pipe_name.c_str(),   // pipe name 
    GENERIC_READ |  // read and write access 
    GENERIC_WRITE,
    0,              // no sharing 
    NULL,           // default security attributes
    OPEN_EXISTING,  // opens existing pipe 
    FILE_ATTRIBUTE_NORMAL, // default attributes 
    NULL);         // no template file 

ConnectNamedPipe 在服务器上然后 returns 与 TRUEGetLastError == 0。但是当它试图调用 ReadFile 来读取管道上的传入数据时,ReadFile 立即 returns FALSEGetLastError==ERROR_BROKEN_PIPE。 在客户端,CreateFile 返回了 GetLastError==231、"All pipe instances are busy"。虽然它是唯一的客户!调用 WaitNamedPipe(pipe, 2000)returns,错误代码为 121,"The semaphore timeout period has expired"。 在 CreateNamedPipe 中增加允许的客户端数量不会改变任何内容。

在客户端尝试连接的那一刻,管道似乎完全坏了。但为什么?客户端和服务器 运行 在同一台机器上,具有相同的用户甚至相同的会话。 然后对 ConnectNamedPipe 的另一个调用失败,GLE=232:"The pipe is being closed".

我还有其他 SECURITY_ATTRIBUTES 用于 CreateNamedPipe,它允许非提升用户连接,但这没有区别。

我也尝试在客户端上使用 CallNamedPipe 结果相同。

PathFileExists 是管道杀手!经过几个小时的尝试,我终于找到了破坏管道的原因:对管道名称上的 PathFileExists 进行简单调用!这是最近在客户端添加的,用于检查管道是否已经创建。我查看了代码更改,但我完全错过了。 PathFileExists 正确 returns true 或 false 但似乎弄乱了管道(正如我所说的那样,它对允许多个客户端连接没有帮助)。啊!!!