GNOME Bugzilla – Bug 587898
I/O timeouts for GSocket
Last modified: 2011-01-03 16:02:48 UTC
The SO_SNDTIMEO and SO_RCVTIMEO sockopts let you set a timeout on a socket such that any operation that blocks for longer than that amount of time will fail with an error. This is useful because otherwise, trying to connect to a non-responding host will take a really really long time to fail (and likewise, if the host/network stops responding after you're connected). Because the sockopts only work with blocking sockets, they can't be used on GSocket fds. So it might be nice to reimplement this functionality at the GSocket level. For blocking sockets, this is pretty simple and mostly just means having g_socket_condition_wait() pass the appropriate timeout to g_poll/WSAWaitForMultipleEvents, and setting @error appropriately if the call times out. The underlying sockopts don't support non-blocking I/O, but we *could* have non-blocking GSockets support timeouts, by changing g_socket_create_source() to create a source that had a timeout associated with it in addition to its pollfds (we could change _g_fd_source and winsock_source to support timeouts directly, or else add a new source that wraps the existing socket source and an ordinary timeout source together into one). This is a little uglier than the blocking case, but it makes the overall API more consistent between blocking and non-blocking... Do we want this? (I've started a patch already...)
Created attachment 147815 [details] [review] Add timeout support to GSocket This adds an io-timeout property to GSocket, plus associated get/set methods, and updates the semantics of various other methods to deal with it. For blocking sockets, this is pretty simple and is entirely handled by the changes to g_socket_condition_wait. For non-blocking sockets, we need to add timeouts to the sources returned by g_socket_create_source(), and then cause I/O methods to return errors if called after timing out. It would have been possible to do this without the priv->timed_out bit, but that would have required additional changes to GSocketInputStream, GSocketOutputStream, GSocketClient, etc to make them support sockets with timeouts. By setting an internal flag on timeout and then treating timeout as "success" from the POV of the source callback, we make the existing code automatically work correctly with timeouting sockets. Since there'd be no way to set priv->timed_out from FDSource in gasynchelper, I merged the unix and winsock socket sources together into one in gsocket.c.
oh, yeah, i'll write a test program before committing. (i'm currently testing via libsoup's timeout-test in a local branch of libsoup modified to use gsocket.)
Created attachment 150872 [details] [review] Merge the unix and windows GSocket sources together
Created attachment 150873 [details] [review] Add timeout support to GSocket Also add options for testing timeouts to socket test programs
ok, i built and tested on windows (mingw/wine) too and it all seems to work, and no one has objected (or read the code at all probably :-})
Created attachment 177405 [details] [review] fix win32 regression revents may have been cleared by GMain before dispatch().
Patch in comment #6 committed.
(In reply to comment #6) > revents may have been cleared by GMain before dispatch(). Hm... where? (By which I mean mostly, is this only a problem on Windows or could it happen on unix as well?)