Notice closed connections sooner
authorDan Winship <danw@gnome.org>
Tue, 18 Aug 2009 02:28:08 +0000 (22:28 -0400)
committerDan Winship <danw@gnome.org>
Tue, 18 Aug 2009 02:47:07 +0000 (22:47 -0400)
Only works on UNIX; Windows has to wait for the GSocket port.

http://bugzilla.gnome.org/show_bug.cgi?id=578990

libsoup/soup-connection.c
libsoup/soup-connection.h
libsoup/soup-session-async.c
libsoup/soup-session-private.h
libsoup/soup-session-sync.c
libsoup/soup-session.c
libsoup/soup-socket.c
libsoup/soup-socket.h

index 0d731c0..78ea311 100644 (file)
@@ -598,10 +598,25 @@ soup_connection_get_proxy_uri (SoupConnection *conn)
 SoupConnectionState
 soup_connection_get_state (SoupConnection *conn)
 {
+       SoupConnectionPrivate *priv;
+
        g_return_val_if_fail (SOUP_IS_CONNECTION (conn),
                              SOUP_CONNECTION_DISCONNECTED);
+       priv = SOUP_CONNECTION_GET_PRIVATE (conn);
+
+#ifdef G_OS_UNIX
+       if (priv->state == SOUP_CONNECTION_IDLE) {
+               GPollFD pfd;
+
+               pfd.fd = soup_socket_get_fd (priv->socket);
+               pfd.events = G_IO_IN;
+               pfd.revents = 0;
+               if (g_poll (&pfd, 1, 0) == 1)
+                       priv->state = SOUP_CONNECTION_REMOTE_DISCONNECTED;
+       }
+#endif
 
-       return SOUP_CONNECTION_GET_PRIVATE (conn)->state;
+       return priv->state;
 }
 
 void
index 68a36ab..2dc6754 100644 (file)
@@ -44,6 +44,7 @@ typedef enum {
        SOUP_CONNECTION_CONNECTING,
        SOUP_CONNECTION_IDLE,
        SOUP_CONNECTION_IN_USE,
+       SOUP_CONNECTION_REMOTE_DISCONNECTED,
        SOUP_CONNECTION_DISCONNECTED
 } SoupConnectionState;
 
index 6045481..cdb9961 100644 (file)
@@ -307,6 +307,8 @@ run_queue (SoupSessionAsync *sa)
        SoupConnection *conn;
        gboolean try_pruning = TRUE, should_prune = FALSE;
 
+       soup_session_cleanup_connections (session, FALSE);
+
  try_again:
        for (item = soup_message_queue_first (queue);
             item && !should_prune;
@@ -354,7 +356,7 @@ run_queue (SoupSessionAsync *sa)
                 * could be sent if we pruned an idle connection from
                 * some other server.
                 */
-               if (soup_session_try_prune_connection (session)) {
+               if (soup_session_cleanup_connections (session, TRUE)) {
                        try_pruning = should_prune = FALSE;
                        goto try_again;
                }
index 65a9718..72b79c5 100644 (file)
@@ -21,7 +21,8 @@ SoupMessageQueueItem *soup_session_make_connect_message (SoupSession          *s
 SoupConnection       *soup_session_get_connection       (SoupSession          *session,
                                                         SoupMessageQueueItem *item,
                                                         gboolean             *try_pruning);
-gboolean              soup_session_try_prune_connection (SoupSession          *session);
+gboolean              soup_session_cleanup_connections  (SoupSession          *session,
+                                                        gboolean              prune_idle);
 void                  soup_session_connection_failed    (SoupSession          *session,
                                                         SoupConnection       *conn,
                                                         guint                 status);
index 662c029..5eecabd 100644 (file)
@@ -201,6 +201,8 @@ wait_for_connection (SoupMessageQueueItem *item)
 
        g_mutex_lock (priv->lock);
 
+       soup_session_cleanup_connections (session, FALSE);
+
  try_again:
        conn = soup_session_get_connection (session, item, &try_pruning);
        if (conn) {
@@ -226,8 +228,11 @@ wait_for_connection (SoupMessageQueueItem *item)
                return conn;
        }
 
-       if (try_pruning && soup_session_try_prune_connection (session))
-               goto try_again;
+       if (try_pruning) {
+               try_pruning = FALSE;
+               if (soup_session_cleanup_connections (session, TRUE))
+                       goto try_again;
+       }
 
        /* Wait... */
        g_cond_wait (priv->cond, priv->lock);
index d4eb1e5..1a778de 100644 (file)
@@ -958,38 +958,35 @@ soup_session_send_queue_item (SoupSession *session,
 }
 
 gboolean
-soup_session_try_prune_connection (SoupSession *session)
+soup_session_cleanup_connections (SoupSession *session,
+                                 gboolean     prune_idle)
 {
        SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
-       GPtrArray *conns;
+       GSList *conns = NULL, *c;
        GHashTableIter iter;
        gpointer conn, host;
-       int i;
-
-       conns = g_ptr_array_new ();
+       SoupConnectionState state;
 
        g_mutex_lock (priv->host_lock);
        g_hash_table_iter_init (&iter, priv->conns);
        while (g_hash_table_iter_next (&iter, &conn, &host)) {
-               /* Don't prune a connection that is currently in use,
-                * or hasn't been used yet.
-                */
-               if (soup_connection_get_state (conn) == SOUP_CONNECTION_IDLE &&
-                   soup_connection_last_used (conn) > 0)
-                       g_ptr_array_add (conns, g_object_ref (conn));
+               state = soup_connection_get_state (conn);
+               if (state == SOUP_CONNECTION_REMOTE_DISCONNECTED ||
+                   (prune_idle && state == SOUP_CONNECTION_IDLE &&
+                    soup_connection_last_used (conn) > 0))
+                       conns = g_slist_prepend (conns, g_object_ref (conn));
        }
        g_mutex_unlock (priv->host_lock);
 
-       if (!conns->len) {
-               g_ptr_array_free (conns, TRUE);
+       if (!conns)
                return FALSE;
-       }
 
-       for (i = 0; i < conns->len; i++) {
-               soup_connection_disconnect (conns->pdata[i]);
-               g_object_unref (conns->pdata[i]);
+       for (c = conns; c; c = c->next) {
+               conn = c->data;
+               soup_connection_disconnect (conn);
+               g_object_unref (conn);
        }
-       g_ptr_array_free (conns, TRUE);
+       g_slist_free (conns);
 
        return TRUE;
 }
index 0c06f0f..e804e27 100644 (file)
@@ -831,6 +831,14 @@ soup_socket_connect_sync (SoupSocket *sock, GCancellable *cancellable)
        return status;
 }
 
+int
+soup_socket_get_fd (SoupSocket *sock)
+{
+       g_return_val_if_fail (SOUP_IS_SOCKET (sock), -1);
+
+       return SOUP_SOCKET_GET_PRIVATE (sock)->sockfd;
+}
+
 static gboolean
 listen_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
 {
index 7b5f58e..079297b 100644 (file)
@@ -63,6 +63,7 @@ void           soup_socket_connect_async      (SoupSocket         *sock,
                                               gpointer            user_data);
 guint          soup_socket_connect_sync       (SoupSocket         *sock,
                                               GCancellable       *cancellable);
+int            soup_socket_get_fd             (SoupSocket         *sock);
 
 gboolean       soup_socket_listen             (SoupSocket         *sock);