diff --git a/ChangeLog b/ChangeLog index 5856731ce..5391afe78 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2007-07-06 Tor Lillqvist + + * 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 * configure.in: Bump version diff --git a/glib/giowin32.c b/glib/giowin32.c index 8632209dc..83cb86cd3 100644 --- a/glib/giowin32.c +++ b/glib/giowin32.c @@ -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);