summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Winship <danw@gnome.org>2015-03-02 20:34:55 -0500
committerDan Winship <danw@gnome.org>2015-03-02 21:28:42 -0500
commit019488c2bcffe70a62166406f39c7905027edb59 (patch)
treedec8bc2e2f1741ee59255a6963e8e7cedfec48ea
parentaa42dd5588eaf617264cc0c9a0984b8c79f22603 (diff)
downloadlibsoup-019488c2bcffe70a62166406f39c7905027edb59.tar.gz
soup-socket: remove close-on-dispose
Setting close-on-dispose=FALSE on a socket would cause it to leak its GSocket. Indeed, there is no way to avoid this, since freeing the GSocket will always close it. Work around the problem in a different way by having the steal() methods steal the GSocket from the SoupSocket, and ensure that it gets freed later along with the stolen GIOStream.
-rw-r--r--libsoup/soup-server.c6
-rw-r--r--libsoup/soup-session.c8
-rw-r--r--libsoup/soup-socket-private.h2
-rw-r--r--libsoup/soup-socket.c35
-rw-r--r--tests/socket-test.c6
5 files changed, 27 insertions, 30 deletions
diff --git a/libsoup/soup-server.c b/libsoup/soup-server.c
index fec9ceb7..77b21422 100644
--- a/libsoup/soup-server.c
+++ b/libsoup/soup-server.c
@@ -2412,9 +2412,9 @@ soup_client_context_steal_connection (SoupClientContext *client)
stream = soup_message_io_steal (client->msg);
if (stream) {
- g_object_set (G_OBJECT (client->sock),
- SOUP_SOCKET_CLOSE_ON_DISPOSE, FALSE,
- NULL);
+ g_object_set_data_full (G_OBJECT (stream), "GSocket",
+ soup_socket_steal_gsocket (client->sock),
+ g_object_unref);
}
socket_disconnected (client->sock, client);
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index a01aa95d..64201838 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -4769,13 +4769,15 @@ soup_session_steal_connection (SoupSession *session,
g_mutex_unlock (&priv->conn_lock);
sock = soup_connection_get_socket (conn);
- g_object_set (G_OBJECT (sock),
- SOUP_SOCKET_CLOSE_ON_DISPOSE, FALSE,
+ g_object_set (sock,
SOUP_SOCKET_TIMEOUT, 0,
NULL);
- g_object_unref (conn);
stream = soup_message_io_steal (item->msg);
+ g_object_set_data_full (G_OBJECT (stream), "GSocket",
+ soup_socket_steal_gsocket (sock),
+ g_object_unref);
+ g_object_unref (conn);
soup_message_queue_item_unref (item);
return stream;
diff --git a/libsoup/soup-socket-private.h b/libsoup/soup-socket-private.h
index 84fad044..c0bb7a19 100644
--- a/libsoup/soup-socket-private.h
+++ b/libsoup/soup-socket-private.h
@@ -9,7 +9,6 @@
#include "soup-socket.h"
#define SOUP_SOCKET_SOCKET_PROPERTIES "socket-properties"
-#define SOUP_SOCKET_CLOSE_ON_DISPOSE "close-on-dispose"
#define SOUP_SOCKET_FD "fd"
#define SOUP_SOCKET_GSOCKET "gsocket"
#define SOUP_SOCKET_IOSTREAM "iostream"
@@ -41,6 +40,7 @@ gboolean soup_socket_handshake_finish (SoupSocket *sock,
gboolean soup_socket_is_readable (SoupSocket *sock);
GSocket *soup_socket_get_gsocket (SoupSocket *sock);
+GSocket *soup_socket_steal_gsocket (SoupSocket *sock);
GIOStream *soup_socket_get_connection (SoupSocket *sock);
GIOStream *soup_socket_get_iostream (SoupSocket *sock);
diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c
index 90db59c4..f10481bd 100644
--- a/libsoup/soup-socket.c
+++ b/libsoup/soup-socket.c
@@ -67,7 +67,6 @@ enum {
PROP_TRUSTED_CERTIFICATE,
PROP_TLS_CERTIFICATE,
PROP_TLS_ERRORS,
- PROP_CLOSE_ON_DISPOSE,
PROP_SOCKET_PROPERTIES,
LAST_PROP
@@ -90,7 +89,6 @@ typedef struct {
guint ssl_strict:1;
guint ssl_fallback:1;
guint clean_dispose:1;
- guint close_on_dispose:1;
guint use_thread_context:1;
gpointer ssl_creds;
@@ -213,7 +211,7 @@ soup_socket_finalize (GObject *object)
g_warning ("Disposing socket %p during connect", object);
g_object_unref (priv->connect_cancel);
}
- if (priv->conn && priv->close_on_dispose) {
+ if (priv->conn) {
if (priv->clean_dispose)
g_warning ("Disposing socket %p while still connected", object);
disconnect_internal (SOUP_SOCKET (object), TRUE);
@@ -363,9 +361,6 @@ soup_socket_set_property (GObject *object, guint prop_id,
priv->clean_dispose = TRUE;
}
break;
- case PROP_CLOSE_ON_DISPOSE:
- priv->close_on_dispose = g_value_get_boolean (value);
- break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -428,9 +423,6 @@ soup_socket_get_property (GObject *object, guint prop_id,
g_value_set_flags (value, priv->tls_errors);
break;
break;
- case PROP_CLOSE_ON_DISPOSE:
- g_value_set_boolean (value, priv->close_on_dispose);
- break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -804,14 +796,6 @@ soup_socket_class_init (SoupSocketClass *socket_class)
"Socket properties",
SOUP_TYPE_SOCKET_PROPERTIES,
G_PARAM_WRITABLE));
-
- g_object_class_install_property (
- object_class, PROP_CLOSE_ON_DISPOSE,
- g_param_spec_boolean (SOUP_SOCKET_CLOSE_ON_DISPOSE,
- "Close socket on disposal",
- "Whether the socket is closed on disposal",
- TRUE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
}
static void
@@ -1139,6 +1123,23 @@ soup_socket_get_gsocket (SoupSocket *sock)
return SOUP_SOCKET_GET_PRIVATE (sock)->gsock;
}
+GSocket *
+soup_socket_steal_gsocket (SoupSocket *sock)
+{
+ SoupSocketPrivate *priv;
+ GSocket *gsock;
+
+ g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
+ priv = SOUP_SOCKET_GET_PRIVATE (sock);
+
+ gsock = priv->gsock;
+ priv->gsock = NULL;
+ g_clear_object (&priv->conn);
+ g_clear_object (&priv->iostream);
+
+ return gsock;
+}
+
gboolean
soup_socket_is_readable (SoupSocket *sock)
{
diff --git a/tests/socket-test.c b/tests/socket-test.c
index cdeace23..52a8fbbf 100644
--- a/tests/socket-test.c
+++ b/tests/socket-test.c
@@ -120,7 +120,6 @@ do_socket_from_fd_client_test (void)
SoupAddress *local, *remote;
GSocketAddress *gaddr;
gboolean is_server;
- int type;
GError *error = NULL;
server = soup_test_server_new (SOUP_TEST_SERVER_DEFAULT);
@@ -143,7 +142,6 @@ do_socket_from_fd_client_test (void)
sock = g_initable_new (SOUP_TYPE_SOCKET, NULL, &error,
SOUP_SOCKET_FD, g_socket_get_fd (gsock),
- SOUP_SOCKET_CLOSE_ON_DISPOSE, FALSE,
NULL);
g_assert_no_error (error);
g_assert_nonnull (sock);
@@ -167,10 +165,6 @@ do_socket_from_fd_client_test (void)
g_object_unref (gaddr);
g_object_unref (sock);
- /* We specified close-on-dispose=FALSE */
- g_socket_get_option (gsock, SOL_SOCKET, SO_TYPE, &type, &error);
- g_assert_no_error (error);
-
g_object_unref (gsock);
g_object_unref (server);