diff options
author | Dan Winship <danw@gnome.org> | 2009-08-17 22:28:08 -0400 |
---|---|---|
committer | Dan Winship <danw@gnome.org> | 2009-08-17 22:47:07 -0400 |
commit | ef7fc0585990b9c2e056596d1850bdb3f6f6dae9 (patch) | |
tree | 28e3b00a55e6c359d1fc06529247bb9fd9d4e960 | |
parent | eb6b12269ec3eea4d1b690f704af15b8cb8acbbe (diff) | |
download | libsoup-ef7fc0585990b9c2e056596d1850bdb3f6f6dae9.tar.gz |
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
-rw-r--r-- | libsoup/soup-connection.c | 17 | ||||
-rw-r--r-- | libsoup/soup-connection.h | 1 | ||||
-rw-r--r-- | libsoup/soup-session-async.c | 4 | ||||
-rw-r--r-- | libsoup/soup-session-private.h | 3 | ||||
-rw-r--r-- | libsoup/soup-session-sync.c | 9 | ||||
-rw-r--r-- | libsoup/soup-session.c | 33 | ||||
-rw-r--r-- | libsoup/soup-socket.c | 8 | ||||
-rw-r--r-- | 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 0d731c00..78ea3111 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 68a36abb..2dc67544 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 60454813..cdb9961b 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 65a97180..72b79c5d 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 662c029c..5eecabd8 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 d4eb1e58..1a778de1 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 0c06f0fe..e804e271 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 7b5f58e1..079297be 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); |