pythonctypesnamed-pipesio-completion-ports

ERROR_NO_MORE_ITEMS with named pipe and IO completion port


I have a simple named pipe server implemented in 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)

It receives data from external program. I expect that GetQueuedCompletionStatus will return only when something arrives to the pipe, but it's not always the case. Sometimes, after it dequeues completion packet, I can see that bytes_available == 0, ret_code == 0 and overlapped_struct.Internal == 256 (which I assume means ERROR_NO_MORE_ITEMS).

Any ideas on why does it happen?


Solution

  • I figured it out. A completion packet is queued after any operation on a pipe. It means that GetQueuedCompletionStatus will return after client connection, write and read operation.

    What was happening in my situation:

    1. I received data from external program. Completion packet was queued.
    2. I read a pipe. Another completion packet was queued.
    3. During the subsequent read, if there was no new data in the pipe, ReadFile returned 0 and overlapped_struct.Internal indicated ERROR_NO_MORE_ITEMS, which is perfectly correct: there was no new data in the pipe.