summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWill Thompson <will.thompson@collabora.co.uk>2012-10-30 16:30:10 +0000
committerWill Thompson <will.thompson@collabora.co.uk>2012-10-30 16:30:10 +0000
commit339c7273dcb604a639ea2b54461b24bd4f252dd6 (patch)
tree42235f762b78762aa10741f760a429f7a0529f00 /src
parent67b18831e0ea40dd3f4438426cfb0f703a3fc971 (diff)
downloadtelepathy-idle-339c7273dcb604a639ea2b54461b24bd4f252dd6.tar.gz
Fix _force_disconnect to actually forcibly disconnect.
Previously, if the network connection had gone away _force_disconnect() would not actually make the connection die any faster, because g_io_stream_close_async() waits for a reply by default. But by pulling the same trick with a cancelled cancellable as is used for ping timeouts, we can fix this. I tested this by: * Connecting to a server (with keepalive-interval=0 to ensure that doesn't interfere). * Pulling out my network cable (breaking the connection) but leaving my wireless connection up. * calling Disconnect() on the connection. Before, the connection would never finish disconnecting; after, the _force_disconnect() timeout actually does something useful and the connection dies properly.
Diffstat (limited to 'src')
-rw-r--r--src/idle-connection.c18
-rw-r--r--src/idle-server-connection.c17
-rw-r--r--src/idle-server-connection.h1
3 files changed, 22 insertions, 14 deletions
diff --git a/src/idle-connection.c b/src/idle-connection.c
index cb008c5..a7c4f73 100644
--- a/src/idle-connection.c
+++ b/src/idle-connection.c
@@ -567,7 +567,9 @@ _force_disconnect (gpointer data)
{
IdleConnection *conn = IDLE_CONNECTION(data);
IdleConnectionPrivate *priv = conn->priv;
- idle_server_connection_disconnect_async(priv->conn, NULL, NULL, NULL);
+
+ IDLE_DEBUG("gave up waiting, forcibly disconnecting");
+ idle_server_connection_force_disconnect(priv->conn);
return FALSE;
}
@@ -830,23 +832,11 @@ static gboolean keepalive_timeout_cb(gpointer user_data) {
gint64 seconds_since_ping = (now - priv->ping_time) / G_USEC_PER_SEC;
if (seconds_since_ping > priv->keepalive_interval * MISSED_KEEPALIVES_BEFORE_DISCONNECTING) {
- GCancellable *kill_me_now = g_cancellable_new();
-
IDLE_DEBUG("haven't heard from the server in %" G_GINT64_FORMAT " seconds "
"(more than %u keepalive intervals)",
seconds_since_ping, MISSED_KEEPALIVES_BEFORE_DISCONNECTING);
- /* Passing a cancelled cancellable to g_io_stream_close_async() stops us
- * waiting for a TCP-level reply from the server which we already know
- * has gone away. Quoth the docs for g_io_stream_close():
- *
- * Cancelling a close will still leave the stream closed, but some
- * streams can use a faster close that doesn't block to e.g. check
- * errors.
- */
- g_cancellable_cancel(kill_me_now);
- idle_server_connection_disconnect_full_async(priv->conn, SERVER_CONNECTION_STATE_REASON_ERROR, kill_me_now, NULL, NULL);
- g_object_unref(kill_me_now);
+ idle_server_connection_force_disconnect(priv->conn);
return FALSE;
}
diff --git a/src/idle-server-connection.c b/src/idle-server-connection.c
index 64cb766..700b5f8 100644
--- a/src/idle-server-connection.c
+++ b/src/idle-server-connection.c
@@ -362,6 +362,23 @@ void idle_server_connection_disconnect_async(IdleServerConnection *conn, GCancel
user_data);
}
+void idle_server_connection_force_disconnect(IdleServerConnection *conn) {
+ /* Passing a cancelled cancellable to g_io_stream_close_async() stops us
+ * waiting for a TCP-level reply from the server which we already know
+ * has gone away. Quoth the docs for g_io_stream_close():
+ *
+ * Cancelling a close will still leave the stream closed, but some
+ * streams can use a faster close that doesn't block to e.g. check
+ * errors.
+ */
+ GCancellable *kill_me_now = g_cancellable_new();
+
+ g_cancellable_cancel(kill_me_now);
+ idle_server_connection_disconnect_full_async(conn,
+ SERVER_CONNECTION_STATE_REASON_ERROR, kill_me_now, NULL, NULL);
+ g_object_unref(kill_me_now);
+}
+
void idle_server_connection_disconnect_full_async(IdleServerConnection *conn, guint reason, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) {
IdleServerConnectionPrivate *priv = IDLE_SERVER_CONNECTION_GET_PRIVATE(conn);
GSimpleAsyncResult *result;
diff --git a/src/idle-server-connection.h b/src/idle-server-connection.h
index 207fedc..8ce36ca 100644
--- a/src/idle-server-connection.h
+++ b/src/idle-server-connection.h
@@ -73,6 +73,7 @@ void idle_server_connection_connect_async(IdleServerConnection *conn, GCancellab
gboolean idle_server_connection_connect_finish(IdleServerConnection *conn, GAsyncResult *result, GError **error);
void idle_server_connection_disconnect_async(IdleServerConnection *conn, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
void idle_server_connection_disconnect_full_async(IdleServerConnection *conn, guint reason, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
+void idle_server_connection_force_disconnect(IdleServerConnection *conn);
gboolean idle_server_connection_disconnect_finish(IdleServerConnection *conn, GAsyncResult *result, GError **error);
void idle_server_connection_send_async(IdleServerConnection *conn, const gchar *cmd, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
gboolean idle_server_connection_send_finish(IdleServerConnection *conn, GAsyncResult *result, GError **error);