ERROR_NO_MORE_ITEMS с именованным каналом и портом завершения ввода-вывода
У меня есть простой сервер именованных каналов, реализованный в python+ctypes:
pipe = windll.kernel32.CreateNamedPipeA('\\\\.\\pipe\\pipe_name', PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE, 1, 0, 0, 0, None)
overlapped_struct = OVERLAPPED()
windll.kernel32.ConnectNamedPipe(pipe, byref(overlapped_struct))
iocp = windll.kernel32.CreateIoCompletionPort(pipe, None, WPARAM(707070707), 0)
while True:
bytes_transferred = DWORD()
completion_key = WPARAM()
overlapped_struct_ptr = POINTER(OVERLAPPED)()
windll.kernel32.GetQueuedCompletionStatus(iocp, byref(bytes_transferred), byref(completion_key), byref(overlapped_struct_ptr), INFINITE)
bytes_available = DWORD()
windll.kernel32.PeekNamedPipe(pipe, None, 0, None, byref(bytes_available))
buf = create_string_buffer(bytes_available.value)
ret_code = windll.kernel32.ReadFile(pipe, byref(buf), bytes_available.value, None, overlapped_struct_ptr)
Получает данные из внешней программы. Я ожидаю что GetQueuedCompletionStatus
вернется только тогда, когда что-то прибудет в трубу, но это не всегда так. Иногда, после того как он завершает пакет завершения, я вижу, что bytes_available == 0
, ret_code == 0
а также overlapped_struct.Internal == 256
(что я предполагаю, означает ERROR_NO_MORE_ITEMS).
Любые идеи о том, почему это происходит?
1 ответ
Решение
Я понял. Пакет завершения ставится в очередь после любой операции над каналом. Это означает, что GetQueuedCompletionStatus
вернется после подключения клиента, операции записи и чтения.
Что происходило в моей ситуации:
- Я получил данные из внешней программы. Пакет завершения был поставлен в очередь.
- Я читаю трубу. Другой пакет завершения был поставлен в очередь.
- Во время последующего чтения, если в канале не было новых данных,
ReadFile
вернул 0 иoverlapped_struct.Internal
указал ERROR_NO_MORE_ITEMS, что совершенно правильно: в канале не было новых данных.