diff options
author | Dan Winship <danw@gnome.org> | 2015-03-02 20:34:55 -0500 |
---|---|---|
committer | Dan Winship <danw@gnome.org> | 2015-03-02 21:28:42 -0500 |
commit | 019488c2bcffe70a62166406f39c7905027edb59 (patch) | |
tree | dec8bc2e2f1741ee59255a6963e8e7cedfec48ea | |
parent | aa42dd5588eaf617264cc0c9a0984b8c79f22603 (diff) | |
download | libsoup-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.c | 6 | ||||
-rw-r--r-- | libsoup/soup-session.c | 8 | ||||
-rw-r--r-- | libsoup/soup-socket-private.h | 2 | ||||
-rw-r--r-- | libsoup/soup-socket.c | 35 | ||||
-rw-r--r-- | tests/socket-test.c | 6 |
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); |