简体   繁体   English

命名管道:ConnectNamedPipe返回ERROR_BROKEN_PIPE后的ReadFile

[英]Named pipe: ReadFile after ConnectNamedPipe return ERROR_BROKEN_PIPE

I reactivated code that I am sure used to work some months ago. 我重新激活了几个月前我确定曾经工作过的代码。 It drives me crazy but it does not anymore. 它让我发疯,但现在已经不复存在了。 I could not find an answer in other questions. 我在其他问题上找不到答案。

On the server side, I create a pipe using 在服务器端,我使用创建管道

#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));

Then a thread waits for incoming clients with ConnectNamedPipe . 然后一个线程等待具有ConnectNamedPipe传入客户端。 ConnectNamedPipe blocks until a client connects with 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 on the server then returns with TRUE and GetLastError == 0 . 然后,服务器上的ConnectNamedPipe将返回TRUEGetLastError == 0 But when it tries to call ReadFile to read incoming data on the pipe, ReadFile immediately returns FALSE and GetLastError==ERROR_BROKEN_PIPE . 但是当它尝试调用ReadFile来读取管道上的传入数据时, ReadFile立即返回FALSEGetLastError==ERROR_BROKEN_PIPE On client side, CreateFile has returned GetLastError==231 , "All pipe instances are busy". 在客户端, CreateFile返回GetLastError==231 ,“所有管道实例都忙”。 Although it is the only client! 虽然它是唯一的客户! A call to WaitNamedPipe(pipe, 2000) returns with error code 121, "The semaphore timeout period has expired". WaitNamedPipe(pipe, 2000)调用返回错误代码121,“信号量超时期限已过期”。 Increasing the number of allowed clients in CreateNamedPipe does not change anything. 增加CreateNamedPipe中允许的客户端数量不会改变任何内容。

It seems the pipe got completely broken in the moment the client tries to connect. 在客户端尝试连接的那一刻,管道似乎完全被破坏了。 But why? 但为什么? Both client and server run on the same machine with same user and even same session. 客户端和服务器在同一台机器上运行,具有相同的用户甚至同一会话。 Another call to ConnectNamedPipe then failed with GLE=232:"The pipe is being closed". 然后另一个对ConnectNamedPipe调用因GLE = 232而失败:“管道正在关闭”。

I also had other SECURITY_ATTRIBUTES for CreateNamedPipe , which shall allow for non-elevated users to connect, but that makes no difference. 我还有CreateNamedPipe其他SECURITY_ATTRIBUTES ,它允许非提升用户连接,但这没有区别。

Also I tried to use CallNamedPipe on the client with the same result. 此外,我尝试在客户端上使用CallNamedPipe ,结果相同。

PathFileExists is the pipe killer! PathFileExists是管道杀手! After hours of trying I finally found what breaks the pipe: a simple call to PathFileExists on the pipe name! 经过几个小时的尝试后,我终于找到了破坏管道的东西:在管道名称上简单调用PathFileExists! This was added recently on the client side to check whether the pipe is already created. 最近在客户端添加了此项以检查管道是否已创建。 I had a look at the code changes but I totally missed that. 我看了一下代码更改,但我完全错过了。 PathFileExists correctly returns true or false but seems to mess up the pipe (as I told it did not help to allow more than one client to connect). PathFileExists正确返回true或false但似乎搞乱了管道(因为我告诉它不允许多个客户端连接)。 Argh!!! 哎呀!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM