When WSAEnumNetworkEvents() signals FD_CONNECT that means that the
authorTor Lillqvist <tml@novell.com>
Fri, 6 Jul 2007 01:22:53 +0000 (01:22 +0000)
committerTor Lillqvist <tml@src.gnome.org>
Fri, 6 Jul 2007 01:22:53 +0000 (01:22 +0000)
2007-07-06  Tor Lillqvist  <tml@novell.com>

* glib/giowin32.c (g_io_win32_check): When WSAEnumNetworkEvents()
signals FD_CONNECT that means that the connection attempt
finished, either successfully or failed. Test explicitly whether
the connnection succeeded and set either G_IO_OUT if it did,
G_IO_ERR|G_IO_HUP if it failed.

Make sure we never set both G_IO_OUT and G_IO_HUP simultaneously
because in Unix poll(2) POLLOUT and POLLHUP are mutually
exclusive.

Ignore whether the caller wants to watch G_IO_HUP or not. Always
select for FD_CLOSE because Unix poll(2) also ignores whether
POLLHUP in set the requested events bitmask or not.

svn path=/trunk/; revision=5600

ChangeLog
glib/giowin32.c

index 5856731..5391afe 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2007-07-06  Tor Lillqvist  <tml@novell.com>
+
+       * glib/giowin32.c (g_io_win32_check): When WSAEnumNetworkEvents()
+       signals FD_CONNECT that means that the connection attempt
+       finished, either successfully or failed. Test explicitly whether
+       the connnection succeeded and set either G_IO_OUT if it did,
+       G_IO_ERR|G_IO_HUP if it failed.
+
+       Make sure we never set both G_IO_OUT and G_IO_HUP simultaneously
+       because in Unix poll(2) POLLOUT and POLLHUP are mutually
+       exclusive.
+
+       Ignore whether the caller wants to watch G_IO_HUP or not. Always
+       select for FD_CLOSE because Unix poll(2) also ignores whether
+       POLLHUP in set the requested events bitmask or not.
+
 Fri Jun 29 2007  Matthias Clasen  <mclasen@redhat.com>
 
        * configure.in: Bump version
index 8632209..83cb86c 100644 (file)
@@ -822,8 +822,7 @@ g_io_win32_prepare (GSource *source,
        event_mask |= (FD_READ | FD_ACCEPT);
       if (watch->condition & G_IO_OUT)
        event_mask |= (FD_WRITE | FD_CONNECT);
-      if (watch->condition & G_IO_HUP)
-       event_mask |= FD_CLOSE;
+      event_mask |= FD_CLOSE;
 
       if (channel->event_mask != event_mask /* || channel->event != watch->pollfd.fd*/)
        {
@@ -936,13 +935,32 @@ g_io_win32_check (GSource *source)
       watch->pollfd.revents = 0;
       if (channel->last_events & (FD_READ | FD_ACCEPT))
        watch->pollfd.revents |= G_IO_IN;
-      if (channel->last_events & (FD_WRITE | FD_CONNECT))
+      if (channel->last_events & FD_WRITE)
        watch->pollfd.revents |= G_IO_OUT;
-      if (watch->pollfd.revents == 0 && (channel->last_events & (FD_CLOSE)))
-       watch->pollfd.revents |= G_IO_HUP;
+      else
+       {
+         /* We have called WSAEnumNetworkEvents() above but it didn't
+          * set FD_WRITE.
+          */
+         if (events.lNetworkEvents & FD_CONNECT)
+           {
+             if (events.iErrorCode[FD_CONNECT_BIT] == 0)
+               watch->pollfd.revents |= G_IO_OUT;
+             else
+               watch->pollfd.revents |= (G_IO_HUP | G_IO_ERR);
+           }
+         if (watch->pollfd.revents == 0 && (channel->last_events & (FD_CLOSE)))
+           watch->pollfd.revents |= G_IO_HUP;
+       }
 
-      if (!channel->write_would_have_blocked && (channel->event_mask & FD_WRITE))
-       watch->pollfd.revents |= G_IO_OUT; /* This sucks but... */
+      /* Regardless of WSAEnumNetworkEvents() result, if watching for
+       * writability, unless last write would have blocked set
+       * G_IO_OUT. But never set both G_IO_OUT and G_IO_HUP.
+       */
+      if (!(watch->pollfd.revents & G_IO_HUP) &&
+         !channel->write_would_have_blocked &&
+         (channel->event_mask & FD_WRITE))
+       watch->pollfd.revents |= G_IO_OUT;
 
       return ((watch->pollfd.revents | buffer_condition) & watch->condition);