I have read-only named pipe and would like to block until there is output available (same behaviour as select
on socket).
I assumed WaitForMultipleObjects
would block if there is no output available, but it does not. What can be done in order to wait efficiently until output is available?
In code below loop is executed 100 times, although PeekNamedPipe
returns 0 bytes available to read on every iteration.
import win32security, win32file, win32pipe, win32event, win32con
pipeName = r"\\.\pipe\test-pipe"
saAttr = win32security.SECURITY_ATTRIBUTES()
namedPipe = win32pipe.CreateNamedPipe(
pipeName,
win32con.PIPE_ACCESS_DUPLEX | win32con.FILE_FLAG_OVERLAPPED, # open mode
win32con.PIPE_TYPE_BYTE, # pipe mode
1, # max instances
1, # out buffer size
1, # in buffer size
0, # timeout
saAttr)
fileHandle = win32file.CreateFile(pipeName,
win32file.GENERIC_READ,
0, None,
win32file.OPEN_EXISTING,
0, None)
for i in range(100):
# would expect this to block until data is available
ret = win32event.WaitForMultipleObjects([fileHandle], 0, win32event.INFINITE)
print(i, ret)
size = 1
buffer, bytesToRead, result = win32pipe.PeekNamedPipe(namedPipe, size)
print(buffer, bytesToRead, result)
if bytesToRead > 0:
res = win32file.ReadFile(namedPipe, size)
I don't have a way to make
WaitForMultipleObjects()
block, but an alternative non-blocking way to check, if there is data in the pipe. Surprisingly win32file.GetFileSize() works with named pipes. Microsoft says it doesn't, but it works for me:The efficiency of the code is debatable. You can see it in action here.
Some more pointers on what I found could be the reason for the unexpected behavior of
WaitForMultipleObjects()
andWaitForSingleObject()
:WaitFor*()
methods need to have theSYNCHRONIZE
access right (MSDN reference)CreateNamedPipe()
have theSYNCHRONIZE
access right (MSDN reference)win32file.WaitFor*()
python wrapper methods is the book "Python Programming On Win32" (on Google Books). But they seem to be waiting for clients connecting, instead of data written to the pipe.