Re: g_source_add_poll or g_io_add_watch in Windows?



Tor Lillqvist wrote:
For the connection I am currently using g_source_add_poll using the socket
FD as returned by socket(AF_INET, SOCK_STREAM, 0).
Under Windows polling does not seem to be working. If I change to using
g_io_channel_win32_new_socket and g_io_add_watch then I can connect clients.

Please note that Windows as such does not have unified "file
descriptors" like UNIX. The small numbers ("file descriptors")
returned by functions like open() or fileno() on Windows are actually
indexes into tables in the C library. They are not known to the kernel
at all. Sockets again, the numbers returned by the socket() and
accept() functions, are totally different. Actually one should call
them SOCKETs, as the typedef used in the Windows headers is SOCKET.
File descriptors and SOCKETs are not interchangeable at all.

The Win32 API uses so-called HANDLEs for its file I/O. (And lots of
other things, too.) SOCKETs are also a kind of HANDLEs. I am not sure
if it is possible to use SOCKETs in Win32 functions like ReadFile()
and WriteFile(), though.

As both SOCKETs and file descriptors are numbers, they can overlap!
I.e., the same number can at the same time both be an open file
descriptor known to the C library your code uses, *and* an open
SOCKET. Thus you should in general not use g_io_channel_unix_new() on
Windows, but instead either g_io_channel_win32_new_stream_socket() or
g_io_channel_win32_new_fd() depending on whether you have a SOCKET or
a file descriptor. If you don't know which one you have, your are out
of luck...

Another important point is that on Windows the fd field of the GPollFD
struct should contain a HANDLE. This is documented in gmain.h:

 * On Win32, the fd in a GPollFD should be Win32 HANDLE (*not* a file
 * descriptor as provided by the C runtime) that can be used by
 * MsgWaitForMultipleObjects. This does *not* include file handles
 * from CreateFile, SOCKETs, nor pipe handles. (But you can use
 * WSAEventSelect to signal events when a SOCKET is readable).

Unfortunately, for my application, I need to be able to set and unset
watches on a particular socket. Currently I am doing this using
g_source_add_poll and g_source_remove_poll.

The best way to create a GPollFD for a SOCKET on Windows is to use
g_io_channel_win32_make_pollfd(). I *think* that it will then work to
add and remove that GPollFD with g_source_add_poll() and
g_source_remove_poll().

Thanks for the ideas - I tried the above idea and that didn't seem to work - it still wasn't polling correctly.
Another possibility is to restructure the code and use
g_io_add_watch() and g_io_remove_watch() instead.
I didn't realise there was a g_io_remove_watch - I don't think it's in the documentation. Anyway that's what I need :) and
my initial experiments seem to be working as required :)
However.... only recently was a patch added to GLib trunk (only) that
fixed the behaviour of a sample program submitted to gtk-devel-list in
May this year. That sample program did something similar to what you
want to do, it added and removed watches. It used slightly different
APIs, though. I can't say whether your code also then (once it is
fixed so that it *could* theoretically work, i.e. for instance doesn't
put a SOCKET in a GPollFD::fd) won't work without that patch.

Sorry. This situation is a mess, that is well known.

I understand - I had to give up porting another app to Windows (not using glib) because of problems with sockets v. file descriptors :(

The GLib main loop and IO channel API can be used in so many ways to
do more or less the same thing. There is no comprehensive test suite
that could be used to verify that it works on Windows. The code is
very fragile. It is quite hard to know whether a change that seems to
help for one use case in fact then breaks some other use case. There
have been bugs open for a long time against the GIOChannel
implementation on Windows that include patches, even, that help the
bug reporter's case, but then again it is hard to say whether they
will break some other use case...

--tml



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]