+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
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*/)
{
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);