summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Winship <danw@novell.com>2005-08-16 14:34:29 +0000
committerDan Winship <danw@src.gnome.org>2005-08-16 14:34:29 +0000
commit5fb4fbfc9b55a5e8b79127d938f390c4d460a86f (patch)
treebadd31056a81f05d40cc57adf731675835777c17
parentfafb234f9843bc6f2a31fbe35ecf13b36310d61a (diff)
downloadlibsoup-5fb4fbfc9b55a5e8b79127d938f390c4d460a86f.tar.gz
Fix a connection leak reported by Tambet.
2005-08-16 Dan Winship <danw@novell.com> Fix a connection leak reported by Tambet. * libsoup/soup-connection.c (send_request): rather than tracking the message progress via signals, call soup_message_send_request_internal() and have it call soup_connection_release() when it's done. (request_restarted, request_done): gone (clear_current_request): handle disconnecting (if necessary) and updating last_used time here. (soup_connection_release): Call clear_current_request(). (dispose): Call clear_current_request() * libsoup/soup-message-client-io.c (soup_message_send_request_internal): New. Takes a SoupConnection in addition to the other args, and passes that on to soup-message-io. * libsoup/soup-message-io.c (SoupMessageIOData): add a SoupConnection field. (io_cleanup): if io->conn is set, unref it. (soup_message_io_stop): if io->conn is set, and we ended in a clean state, call soup_connection_release() on it. (soup_message_io_client): Add a SoupConnection arg, which gets reffed and stored in io->conn. * TODO: misc updates
-rw-r--r--ChangeLog29
-rw-r--r--libsoup/soup-connection.c48
-rw-r--r--libsoup/soup-message-client-io.c9
-rw-r--r--libsoup/soup-message-io.c11
-rw-r--r--libsoup/soup-message-private.h6
5 files changed, 65 insertions, 38 deletions
diff --git a/ChangeLog b/ChangeLog
index 358655af..6677fa00 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2005-08-16 Dan Winship <danw@novell.com>
+
+ Fix a connection leak reported by Tambet.
+
+ * libsoup/soup-connection.c (send_request): rather than tracking
+ the message progress via signals, call
+ soup_message_send_request_internal() and have it call
+ soup_connection_release() when it's done.
+ (request_restarted, request_done): gone
+ (clear_current_request): handle disconnecting (if necessary) and
+ updating last_used time here.
+ (soup_connection_release): Call clear_current_request().
+ (dispose): Call clear_current_request()
+
+ * libsoup/soup-message-client-io.c
+ (soup_message_send_request_internal): New. Takes a SoupConnection
+ in addition to the other args, and passes that on to
+ soup-message-io.
+
+ * libsoup/soup-message-io.c (SoupMessageIOData): add a
+ SoupConnection field.
+ (io_cleanup): if io->conn is set, unref it.
+ (soup_message_io_stop): if io->conn is set, and we ended in a
+ clean state, call soup_connection_release() on it.
+ (soup_message_io_client): Add a SoupConnection arg, which gets
+ reffed and stored in io->conn.
+
+ * TODO: misc updates
+
2005-06-20 Dan Winship <danw@novell.com>
* configure.in: Bump version to 2.2.4
diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c
index 17676f99..88ede8aa 100644
--- a/libsoup/soup-connection.c
+++ b/libsoup/soup-connection.c
@@ -25,6 +25,7 @@
#include "soup-connection.h"
#include "soup-marshal.h"
#include "soup-message.h"
+#include "soup-message-private.h"
#include "soup-message-filter.h"
#include "soup-misc.h"
#include "soup-socket.h"
@@ -79,8 +80,8 @@ static void set_property (GObject *object, guint prop_id,
static void get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec);
-static void request_done (SoupMessage *req, gpointer user_data);
static void send_request (SoupConnection *conn, SoupMessage *req);
+static void clear_current_request (SoupConnection *conn);
static void
init (GObject *object)
@@ -113,8 +114,7 @@ dispose (GObject *object)
{
SoupConnection *conn = SOUP_CONNECTION (object);
- if (conn->priv->cur_req)
- request_done (conn->priv->cur_req, conn);
+ clear_current_request (conn);
soup_connection_disconnect (conn);
G_OBJECT_CLASS (parent_class)->dispose (object);
@@ -319,6 +319,11 @@ static void
clear_current_request (SoupConnection *conn)
{
if (conn->priv->cur_req) {
+ if (!soup_message_is_keepalive (conn->priv->cur_req))
+ soup_connection_disconnect (conn);
+ else
+ conn->priv->last_used = time (NULL);
+
g_object_remove_weak_pointer (G_OBJECT (conn->priv->cur_req),
(gpointer *)conn->priv->cur_req);
conn->priv->cur_req = NULL;
@@ -651,47 +656,16 @@ soup_connection_last_used (SoupConnection *conn)
}
static void
-request_restarted (SoupMessage *req, gpointer conn)
-{
- if (!soup_message_is_keepalive (req))
- soup_connection_disconnect (conn);
-}
-
-static void
-request_done (SoupMessage *req, gpointer user_data)
-{
- SoupConnection *conn = user_data;
-
- clear_current_request (conn);
- conn->priv->last_used = time (NULL);
-
- if (!soup_message_is_keepalive (req))
- soup_connection_disconnect (conn);
-
- g_signal_handlers_disconnect_by_func (req, request_done, conn);
- g_signal_handlers_disconnect_by_func (req, request_restarted, conn);
- g_object_unref (conn);
-}
-
-static void
send_request (SoupConnection *conn, SoupMessage *req)
{
- g_object_ref (conn);
-
if (req != conn->priv->cur_req) {
set_current_request (conn, req);
-
- g_signal_connect (req, "restarted",
- G_CALLBACK (request_restarted), conn);
- g_signal_connect (req, "finished",
- G_CALLBACK (request_done), conn);
-
if (conn->priv->filter)
soup_message_filter_setup_message (conn->priv->filter, req);
}
- soup_message_send_request (req, conn->priv->socket,
- conn->priv->proxy_uri != NULL);
+ soup_message_send_request_internal (req, conn->priv->socket, conn,
+ conn->priv->proxy_uri != NULL);
}
/**
@@ -742,7 +716,7 @@ soup_connection_release (SoupConnection *conn)
{
g_return_if_fail (SOUP_IS_CONNECTION (conn));
- conn->priv->in_use = FALSE;
+ clear_current_request (conn);
}
/**
diff --git a/libsoup/soup-message-client-io.c b/libsoup/soup-message-client-io.c
index fdc64294..596b30d8 100644
--- a/libsoup/soup-message-client-io.c
+++ b/libsoup/soup-message-client-io.c
@@ -172,8 +172,15 @@ void
soup_message_send_request (SoupMessage *req, SoupSocket *sock,
gboolean is_via_proxy)
{
+ soup_message_send_request_internal (req, sock, NULL, is_via_proxy);
+}
+
+void
+soup_message_send_request_internal (SoupMessage *req, SoupSocket *sock,
+ SoupConnection *conn, gboolean is_via_proxy)
+{
soup_message_cleanup_response (req);
- soup_message_io_client (req, sock,
+ soup_message_io_client (req, sock, conn,
get_request_headers,
parse_response_headers,
GUINT_TO_POINTER (is_via_proxy));
diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c
index 7350378b..f28833d0 100644
--- a/libsoup/soup-message-io.c
+++ b/libsoup/soup-message-io.c
@@ -12,6 +12,7 @@
#include <stdlib.h>
#include <string.h>
+#include "soup-connection.h"
#include "soup-message.h"
#include "soup-message-private.h"
#include "soup-socket.h"
@@ -36,6 +37,7 @@ typedef enum {
typedef struct {
SoupSocket *sock;
+ SoupConnection *conn;
SoupMessageIOMode mode;
SoupMessageIOState read_state;
@@ -81,6 +83,8 @@ io_cleanup (SoupMessage *msg)
if (io->sock)
g_object_unref (io->sock);
+ if (io->conn)
+ g_object_unref (io->conn);
if (io->read_buf)
g_byte_array_free (io->read_buf, TRUE);
@@ -122,6 +126,8 @@ soup_message_io_stop (SoupMessage *msg)
if (io->read_state != SOUP_MESSAGE_IO_STATE_DONE)
soup_socket_disconnect (io->sock);
+ else if (io->conn)
+ soup_connection_release (io->conn);
}
#define SOUP_MESSAGE_IO_EOL "\r\n"
@@ -698,6 +704,7 @@ new_iostate (SoupMessage *msg, SoupSocket *sock, SoupMessageIOMode mode,
* soup_message_io_client:
* @msg: a #SoupMessage
* @sock: socket to send @msg across
+ * @conn: the connection that owns @sock (or %NULL)
* @get_headers_cb: callback function to generate request headers
* @parse_headers_cb: callback function to parse response headers
* @user_data: data to pass to the callbacks
@@ -708,6 +715,7 @@ new_iostate (SoupMessage *msg, SoupSocket *sock, SoupMessageIOMode mode,
**/
void
soup_message_io_client (SoupMessage *msg, SoupSocket *sock,
+ SoupConnection *conn,
SoupMessageGetHeadersFn get_headers_cb,
SoupMessageParseHeadersFn parse_headers_cb,
gpointer user_data)
@@ -717,6 +725,9 @@ soup_message_io_client (SoupMessage *msg, SoupSocket *sock,
io = new_iostate (msg, sock, SOUP_MESSAGE_IO_CLIENT,
get_headers_cb, parse_headers_cb, user_data);
+ if (conn)
+ io->conn = g_object_ref (conn);
+
io->read_body = &msg->response;
io->write_body = &msg->request;
diff --git a/libsoup/soup-message-private.h b/libsoup/soup-message-private.h
index c17bc78d..a705ad1a 100644
--- a/libsoup/soup-message-private.h
+++ b/libsoup/soup-message-private.h
@@ -39,8 +39,14 @@ typedef guint (*SoupMessageParseHeadersFn)(SoupMessage *msg,
guint *content_len,
gpointer user_data);
+void soup_message_send_request_internal (SoupMessage *req,
+ SoupSocket *sock,
+ SoupConnection *conn,
+ gboolean via_proxy);
+
void soup_message_io_client (SoupMessage *msg,
SoupSocket *sock,
+ SoupConnection *conn,
SoupMessageGetHeadersFn get_headers_cb,
SoupMessageParseHeadersFn parse_headers_cb,
gpointer user_data);