The following code does not work correctly on Windows (but does on Linux):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setblocking(True)
sock.connect(address)
gobject.io_add_watch(
sock.fileno(),
gobject.IO_OUT | gobject.IO_ERR | gobject.IO_HUP,
callback)
Snippets of comments in various places in the glib source, and other places mention that in Windows, sockets are put in non-blocking mode during polling. As a result the callback self.outgoing_cb
is constantly called, and writing to the socket fails with this error message:
[Errno 10035] A non-blocking socket operation could not be completed immediately
Calling sock.setblocking(True)
prior to writing does not seem to circumvent this. By lowering the priority of the polling, and ignoring the error message, it works as expected, but throws far to many events, and consumes a lot of CPU. Is there a way around this limitation in Windows?
Update
I might point out, that the whole point of polling for POLLOUT
is that when you make the write call you won't get EAGAIN
/EWOULDBLOCK
. The strange error message that I'm getting, I believe would be the Windows equivalent of those 2 error codes. In other words, I'm getting gobject.IO_OUT
events when the socket will not let me write successfully, and putting it into blocking mode still gives me this inappropriate error.
Another update
On Linux, where this works correctly, the socket is not switched to non-blocking mode, and I receive IO_OUT
, when the socket will let me write without blocking, or throwing an error. It's this functionality I want to best emulate/restore under Windows.
Further notes
From man poll
:
poll() performs a similar task to select(2): it waits for one of a set
of file descriptors to become ready to perform I/O.
POLLOUT
Writing now will not block.
From man select
:
A file descriptor is considered ready if it is possible to perform the corre‐
sponding I/O operation (e.g., read(2)) without blocking.
Is there a problem with doing non-blocking I/O? It seems kind of strange to use polling loops if you're using blocking I/O.
When I write programs like this I tend to do the following:
Buffer the bytes I want to send to the file descriptor.
Only ask for IO_OUT
(or the poll()
equivalent, POLLOUT
) events when said buffer is non-empty.
When poll()
(or equivalent) has signaled that you're ready to write, issue the write. If you get EAGAIN
/EWOULDBLOCK
, remove the bytes you successfully wrote from the buffer and wait for the next time you get signaled. If you successfully wrote the entire buffer, then stop asking for POLLOUT
so you don't spuriously wake up.
(My guess is that the Win32 bindings are using WSAEventSelect and WaitForMultipleObjects()
to simulate poll()
, but the result is the same...)
I'm not sure how your desired approach with blocking sockets would work. You are "waking up" constantly because you asked to wake you up when you can write. You only want to specify that when you have data to write... But then, when it wakes you up, the system won't really tell you how much data you can write without blocking, so that's a good reason to use non-blocking I/O.