2016-03-16 2 views
3

Я активировал код, который, как я уверен, работал несколько месяцев назад. Это сводит меня с ума, но это уже не так. Я не мог найти ответа в других вопросах.Именованная труба: ReadFile после возврата ConnectNamedPipe 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 на сервере, то возвращается с TRUE и GetLastError == 0. Но когда он пытается позвонить ReadFile, чтобы читать входящие данные на трубе, ReadFile немедленно возвращает FALSE и GetLastError==ERROR_BROKEN_PIPE. На стороне клиента CreateFile вернул GetLastError==231, «Все экземпляры труб заняты». Хотя это единственный клиент! Вызов WaitNamedPipe(pipe, 2000) возвращается с кодом ошибки 121, «Срок таймаута семафора истек». Увеличение количества разрешенных клиентов в CreateNamedPipe ничего не меняет.

Кажется, что труба полностью сломана в момент, когда клиент пытается подключиться. Но почему? Оба клиента и сервер работают на одном компьютере с одним и тем же пользователем и даже с тем же сеансом. Еще один вызов ConnectNamedPipe, а затем с GLE = 232: «Труба закрыта».

У меня также были другие SECURITY_ATTRIBUTES для CreateNamedPipe, которые должны позволять пользователям не приподнятым пользователям подключаться, но это не имеет значения.

Также я попытался использовать CallNamedPipe на клиенте с тем же результатом.

+1

Просьба указать [Минимальный, полный и проверенный пример] (http://stackoverflow.com/help/mcve), показывающий, как вы используете трубку на обоих концах. –

+0

Я предполагаю, что у вас есть какая-то программа-изгоев, которая подключается к вашей трубе и затем закрывается. Вы можете попробовать изменить название трубы и посмотреть, что-нибудь изменится. Если это не удается, я рекомендую использовать [Process Monitor] (https://technet.microsoft.com/en-us/sysinternals/bb896645), чтобы найти причину. – rodrigo

+0

Если предположение Родриго правильное (и это кажется хорошим), возможно, стоит попробовать GetNamedPipeClientProcessId() на сервере сразу же после успешного завершения ConnectNamedPipe(). –

ответ

3

PathFileExists - убийца трубы! После нескольких часов попыток я наконец нашел то, что ломает трубку: простой вызов PathFileExists по имени трубы! Это было добавлено недавно на клиентской стороне, чтобы проверить, уже ли создан канал. Я посмотрел на изменения кода, но я полностью пропустил это. PathFileExists правильно возвращает true или false, но, похоже, испортил канал (как я сказал, это не помогло подключить более одного клиента). Argh !!!

+0

Удивительно, как часто создание MCVE может сделать причину проблемы очевидной. :-) Спасибо за сообщение. –

+0

Смешно, похоже, что 'PathFileExists' открывает и закрывает файл, или что-то в этом роде. Поэтому я был частично прав с моим предположением выше. Кстати, вы должны принять этот ответ, даже если он ваш. – rodrigo

+0

большое спасибо всем участникам! – user2452157

Смежные вопросы