From ef7fc0585990b9c2e056596d1850bdb3f6f6dae9 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 17 Aug 2009 22:28:08 -0400 Subject: [PATCH] Notice closed connections sooner 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 | 17 ++++++++++++++++- libsoup/soup-connection.h | 1 + libsoup/soup-session-async.c | 4 +++- libsoup/soup-session-private.h | 3 ++- libsoup/soup-session-sync.c | 9 +++++++-- libsoup/soup-session.c | 33 +++++++++++++++------------------ libsoup/soup-socket.c | 8 ++++++++ libsoup/soup-socket.h | 1 + 8 files changed, 53 insertions(+), 23 deletions(-) diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index 0d731c0..78ea311 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -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 diff --git a/libsoup/soup-connection.h b/libsoup/soup-connection.h index 68a36ab..2dc6754 100644 --- a/libsoup/soup-connection.h +++ b/libsoup/soup-connection.h @@ -44,6 +44,7 @@ typedef enum { SOUP_CONNECTION_CONNECTING, SOUP_CONNECTION_IDLE, SOUP_CONNECTION_IN_USE, + SOUP_CONNECTION_REMOTE_DISCONNECTED, SOUP_CONNECTION_DISCONNECTED } SoupConnectionState; diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c index 6045481..cdb9961 100644 --- a/libsoup/soup-session-async.c +++ b/libsoup/soup-session-async.c @@ -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; } diff --git a/libsoup/soup-session-private.h b/libsoup/soup-session-private.h index 65a9718..72b79c5 100644 --- a/libsoup/soup-session-private.h +++ b/libsoup/soup-session-private.h @@ -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); diff --git a/libsoup/soup-session-sync.c b/libsoup/soup-session-sync.c index 662c029..5eecabd 100644 --- a/libsoup/soup-session-sync.c +++ b/libsoup/soup-session-sync.c @@ -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); diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index d4eb1e5..1a778de 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -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; } diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index 0c06f0f..e804e27 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -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) { diff --git a/libsoup/soup-socket.h b/libsoup/soup-socket.h index 7b5f58e..079297b 100644 --- a/libsoup/soup-socket.h +++ b/libsoup/soup-socket.h @@ -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); -- 2.7.4