summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Winship <danw@gnome.org>2009-08-17 22:28:08 -0400
committerDan Winship <danw@gnome.org>2009-08-17 22:47:07 -0400
commitef7fc0585990b9c2e056596d1850bdb3f6f6dae9 (patch)
tree28e3b00a55e6c359d1fc06529247bb9fd9d4e960
parenteb6b12269ec3eea4d1b690f704af15b8cb8acbbe (diff)
downloadlibsoup-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.c17
-rw-r--r--libsoup/soup-connection.h1
-rw-r--r--libsoup/soup-session-async.c4
-rw-r--r--libsoup/soup-session-private.h3
-rw-r--r--libsoup/soup-session-sync.c9
-rw-r--r--libsoup/soup-session.c33
-rw-r--r--libsoup/soup-socket.c8
-rw-r--r--libsoup/soup-socket.h1
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);