g_io_add_watch and non-blocking io on windows
Hello! I am trying to discover how to use non-blocking io with glib on windows. I am trying such program: /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ #include glib.h #ifdef G_OS_WIN32 #include winsock2.h #include ws2tcpip.h #endif gboolean connect_cb (GIOChannel *io_channel, GIOCondition condition, gpointer data) { switch (condition) { case G_IO_OUT: g_debug (Connected.); break; case G_IO_ERR: g_debug (Error!); break; } return FALSE; } int main (int argc, char *argv[]) { #ifdef G_OS_WIN32 int ret; WSADATA wsaData; SOCKET sd; struct sockaddr_in target; struct hostent*hptr; u_long mode = 1; GMainLoop *loop; GIOChannel*io_channel; GSource *source; ret = WSAStartup (0x0202, wsaData); if (ret) { g_error (WSAStaroup failed with error %d, ret); } sd = socket (AF_INET, SOCK_STREAM, 0); if (sd == INVALID_SOCKET) { g_error (socket failed with error %d, WSAGetLastError ()); } target.sin_family = AF_INET; target.sin_port = htons (80); if ( (hptr = gethostbyname (somehost.com)) == NULL) { g_error (gethostbyname () failed with error %d\n, WSAGetLastError ()); } memcpy ((target.sin_addr.s_addr), hptr-h_addr_list[0], sizeof (target.sin_addr.s_addr)); if (ioctlsocket(sd, FIONBIO, mode) == SOCKET_ERROR) { g_error(ioctlsocket() failed \n); } loop = g_main_loop_new (NULL, FALSE); io_channel = g_io_channel_win32_new_socket (sd); g_io_channel_set_encoding (io_channel, NULL, NULL); g_io_channel_set_buffered (io_channel, FALSE); g_io_add_watch (io_channel, G_IO_ERR | G_IO_OUT, connect_cb, NULL); g_debug (Executing connect async...); ret = connect (sd, (const struct sockaddr *) target, sizeof (target)); if (ret == SOCKET_ERROR) { if (WSAGetLastError () != WSAEWOULDBLOCK) g_error (connect () failed with error %d\n, WSAGetLastError ()); } g_debug (Starting GMainLoop...); g_main_loop_run (loop); #endif return 0; } /* END */ My problem is that condition parameter in callback is always G_IO_OUT even if target host:port is unreachable. How can I discover that connect was unsuccessfull? Thanx. // wbr Alexander ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: g_io_add_watch and non-blocking io on windows
Alexander Semyonov writes: My problem is that condition parameter in callback is always G_IO_OUT even if target host:port is unreachable. How can I discover that connect was unsuccessfull? Yeah. The code in giowin32.c is known to be rather fragile and indeed buggy. This might be fixed by a patch attached to bug #357674. The bug description seems partly similar. Unfortunately the patch is not attached to the bug, but just as a pointer to a zip file on the web that doesn't exist any longer, sigh. (Yeah, I said in December last year in that bug that I would look into it soon... Please consider half a year later soon...) Daniel, you commented on that bug and apparently did manage to download the zip file with the patch when it still was available, do you still have it? --tml ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: g_io_add_watch and non-blocking io on windows
Tor Lillqvist writes: Daniel, you commented on that bug and apparently did manage to download the zip file with the patch when it still was available, do you still have it? (I got it, thanks. And of course, right after that, I did find it on my disk after all... Will have a close look at it and see if it helps Alexander's problem, for instance.) --tml ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: g_io_add_watch and non-blocking io on windows
Alexander Semyonov writes: My problem is that condition parameter in callback is always G_IO_OUT even if target host:port is unreachable. How can I discover that connect was unsuccessfull? Thanx. The root cause for this apparently is that the giowin32.c code doesn't check whether the connection actually succeeded or not when WSAEnumNetworkEvents() returns with the FD_CONNECT bit set in the WSANETWORKEVENTS. Reading the fine documentation for connect() on MSDN, it clearly says that when using the WSAEventSelect() mechanism (which giowin32.c does), the event will fire and WSAEnumNetworkEvents() will return with the FD_CONNECT bit set in WSANETWORKEVENTS.lNetworkEvents when the connection attempt has finished, successfuly or not. Whether it succeeded or not should be checked from the error code corresponding to FD_CONNECT in the WSANETWORKEVENTS.iErrorCode. This is what giowin32.c should do, if it needs to differentiate. (Which is not 100% clear, read on...) What do you expect to happen if the connection fails? Presumably that your callback function is called with G_IO_ERR? Is that what happens on Unix? (Your test program only contains Win32 code to set up the socket.) Or is that G_IO_ERR just your guess? Could it be G_IO_HUP that one should look for instead? (That wouldn't be entirely logical, if there hasn't been any connection in the first place, how can it be hung up...?) Or could it really be that G_IO_OUT is actually the right event to get even when the connection didn't succeed, and it's then up to notice that the socket is not connected only when actually attempting to send that? That would be rather silly, I think. --tml ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: g_io_add_watch and non-blocking io on windows
The patch attached to bug #357674 didn't help for this problem after all. Will have to read through that bug description and the patch closely and commit if I am reasonably convinced it doesn't cause any regressions... Anyway, it turns out that at least on Linux poll() sets POLLERR|POLLHUP when it returns after polling a socket that is being asynchronously connected and the connection finally has failed. So g_io_win32_check() in giowin32.c should also set G_IO_ERR and G_IO_HUP in this case. I read in http://www.opengroup.org/onlinepubs/95399/functions/poll.html that POLLOUT and POLLHUP are mutually exclusive. I guess this means GLib should also guarantee that G_IO_OUT and G_IO_HUP are mutually exclusive. But on the other hand, if I understand the documentaion correctly, Win32 signals FD_CLOSE only once, so do we need to make that sticky once received once? Sigh... Anyway, I committed a patch to giowin32.c that makes your test program's callback function receive G_IO_ERR when the connect() fails. (After that the program goes into a tight loop and keeps doing g_main_poll() even if there is nothing to poll...) 2007-07-06 Tor Lillqvist [EMAIL PROTECTED] * 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. --tml ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list