[gnome-remote-desktop] session: Stop trying to stop the session, when it is already destroyed
- From: Jonas Ådahl <jadahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-remote-desktop] session: Stop trying to stop the session, when it is already destroyed
- Date: Tue, 7 Dec 2021 21:21:49 +0000 (UTC)
commit aed99b38dc6785eee3722d6523cbfe49a8684036
Author: Pascal Nowack <Pascal Nowack gmx de>
Date: Wed Nov 24 17:03:11 2021 +0100
session: Stop trying to stop the session, when it is already destroyed
In order to start a remote desktop session, gnome-remote-desktop calls
several dbus methods on the remote desktop- and screencast interface of
mutter.
These calls use in glib internally GTasks and will always run their
async-ready-callback, when the task is done, aborted, or cancelled.
This also applies to situations, where the session is immediately
stopped or destroyed.
In such cases, the callback should not be handled any more, as parts of
the session are already destroyed, due to the session already been
stopped, or the complete session is already destroyed.
The result is usually a crash, as gnome-remote-desktop tries to stop
the session, although it is already stopped or destroyed.
To prevent these situations, always cancel the cancellable, when
stopping the session.
When a async-ready-callback is called, don't directly derenference the
user date.
Instead, call the finish function first and check the error code.
When the cancellable was cancelled, the finish function will not return
successfully and set the error.
The error code will in such cases be G_IO_ERROR_CANCELLED.
If that is the case, just return, as the session is already stopped.
src/grd-session.c | 149 +++++++++++++++++++++++++++++++++---------------------
1 file changed, 91 insertions(+), 58 deletions(-)
---
diff --git a/src/grd-session.c b/src/grd-session.c
index 32fdc671..057bb03e 100644
--- a/src/grd-session.c
+++ b/src/grd-session.c
@@ -93,6 +93,9 @@ grd_session_stop (GrdSession *session)
{
GrdSessionPrivate *priv = grd_session_get_instance_private (session);
+ if (priv->cancellable && g_cancellable_is_cancelled (priv->cancellable))
+ return;
+
GRD_SESSION_GET_CLASS (session)->stop (session);
if (priv->remote_desktop_session && priv->started)
@@ -107,11 +110,17 @@ grd_session_stop (GrdSession *session)
}
}
+ if (priv->cancellable)
+ g_cancellable_cancel (priv->cancellable);
+
g_clear_signal_handler (&priv->caps_lock_state_changed_id,
priv->remote_desktop_session);
g_clear_signal_handler (&priv->num_lock_state_changed_id,
priv->remote_desktop_session);
+ if (priv->stream)
+ grd_stream_disconnect_proxy_signals (priv->stream);
+
g_clear_object (&priv->remote_desktop_session);
g_clear_object (&priv->screen_cast_session);
@@ -437,23 +446,27 @@ on_session_start_finished (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
- GrdSession *session = user_data;
- GrdSessionPrivate *priv = grd_session_get_instance_private (session);
- GrdDBusRemoteDesktopSession *proxy = priv->remote_desktop_session;
- GError *error = NULL;
+ GrdDBusRemoteDesktopSession *proxy;
+ GrdSession *session;
+ GrdSessionPrivate *priv;
+ g_autoptr (GError) error = NULL;
+ proxy = GRD_DBUS_REMOTE_DESKTOP_SESSION (object);
if (!grd_dbus_remote_desktop_session_call_start_finish (proxy,
result,
&error))
{
- g_warning ("Failed to start session: %s", error->message);
- g_error_free (error);
-
- grd_session_stop (session);
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+ g_warning ("Failed to start session: %s", error->message);
+ grd_session_stop (GRD_SESSION (user_data));
return;
}
+ session = GRD_SESSION (user_data);
+ priv = grd_session_get_instance_private (session);
+
priv->started = TRUE;
}
@@ -474,23 +487,26 @@ on_screen_cast_stream_proxy_acquired (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
- GrdSession *session = user_data;
- GrdSessionPrivate *priv = grd_session_get_instance_private (session);
GrdDBusScreenCastStream *stream_proxy;
- GError *error = NULL;
+ GrdSession *session;
+ GrdSessionPrivate *priv;
+ g_autoptr (GError) error = NULL;
GrdStream *stream;
stream_proxy = grd_dbus_screen_cast_stream_proxy_new_finish (result, &error);
if (!stream_proxy)
{
- g_warning ("Failed to acquire stream proxy: %s", error->message);
- g_error_free (error);
-
- grd_session_stop (session);
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+ g_warning ("Failed to acquire stream proxy: %s", error->message);
+ grd_session_stop (GRD_SESSION (user_data));
return;
}
+ session = GRD_SESSION (user_data);
+ priv = grd_session_get_instance_private (session);
+
stream = grd_stream_new (priv->context, stream_proxy);
g_signal_connect (stream, "ready", G_CALLBACK (on_stream_ready),
session);
@@ -506,26 +522,30 @@ on_record_monitor_finished (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
- GrdSession *session = user_data;
- GrdSessionPrivate *priv = grd_session_get_instance_private (session);
- GrdDBusScreenCastSession *proxy = priv->screen_cast_session;
- g_autofree char *stream_path = NULL;
- GError *error = NULL;
+ GrdDBusScreenCastSession *proxy;
+ GrdSession *session;
+ GrdSessionPrivate *priv;
GDBusConnection *connection;
+ g_autofree char *stream_path = NULL;
+ g_autoptr (GError) error = NULL;
+ proxy = GRD_DBUS_SCREEN_CAST_SESSION (object);
if (!grd_dbus_screen_cast_session_call_record_monitor_finish (proxy,
&stream_path,
result,
&error))
{
- g_warning ("Failed to record monitor: %s", error->message);
- g_error_free (error);
-
- grd_session_stop (session);
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+ g_warning ("Failed to record monitor: %s", error->message);
+ grd_session_stop (GRD_SESSION (user_data));
return;
}
+ session = GRD_SESSION (user_data);
+ priv = grd_session_get_instance_private (session);
+
connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (proxy));
grd_dbus_screen_cast_stream_proxy_new (connection,
G_DBUS_PROXY_FLAGS_NONE,
@@ -541,25 +561,28 @@ on_screen_cast_session_proxy_acquired (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
- GrdSession *session = user_data;
- GrdSessionPrivate *priv = grd_session_get_instance_private (session);
GrdDBusScreenCastSession *session_proxy;
+ GrdSession *session;
+ GrdSessionPrivate *priv;
GVariantBuilder properties_builder;
- GError *error = NULL;
+ g_autoptr (GError) error = NULL;
session_proxy =
grd_dbus_screen_cast_session_proxy_new_finish (result, &error);
if (!session_proxy)
{
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
g_warning ("Failed to acquire screen cast session proxy: %s\n",
error->message);
- g_error_free (error);
-
- grd_session_stop (session);
-
+ grd_session_stop (GRD_SESSION (user_data));
return;
}
+ session = GRD_SESSION (user_data);
+ priv = grd_session_get_instance_private (session);
+
priv->screen_cast_session = session_proxy;
g_variant_builder_init (&properties_builder, G_VARIANT_TYPE ("a{sv}"));
@@ -581,28 +604,31 @@ on_screen_cast_session_created (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
- GrdSession *session = user_data;
- GrdSessionPrivate *priv = grd_session_get_instance_private (session);
GrdDBusScreenCast *screen_cast_proxy;
- g_autofree char *session_path = NULL;
- GError *error = NULL;
+ GrdSession *session;
+ GrdSessionPrivate *priv;
GDBusConnection *connection;
+ g_autofree char *session_path = NULL;
+ g_autoptr (GError) error = NULL;
- screen_cast_proxy = grd_context_get_screen_cast_proxy (priv->context);
+ screen_cast_proxy = GRD_DBUS_SCREEN_CAST (source_object);
if (!grd_dbus_screen_cast_call_create_session_finish (screen_cast_proxy,
&session_path,
res,
&error))
{
- g_warning ("Failed to start screen cast session: %s\n", error->message);
- g_error_free (error);
-
- grd_session_stop (session);
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+ g_warning ("Failed to start screen cast session: %s\n", error->message);
+ grd_session_stop (GRD_SESSION (user_data));
return;
}
+ session = GRD_SESSION (user_data);
+ priv = grd_session_get_instance_private (session);
connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (screen_cast_proxy));
+
grd_dbus_screen_cast_session_proxy_new (connection,
G_DBUS_PROXY_FLAGS_NONE,
MUTTER_SCREEN_CAST_BUS_NAME,
@@ -730,11 +756,11 @@ on_remote_desktop_session_proxy_acquired (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
- GrdSession *session = user_data;
- GrdSessionPrivate *priv = grd_session_get_instance_private (session);
- GrdSessionClass *klass = GRD_SESSION_GET_CLASS (session);
GrdDBusRemoteDesktopSession *session_proxy;
- GError *error = NULL;
+ GrdSession *session;
+ GrdSessionPrivate *priv;
+ GrdSessionClass *klass;
+ g_autoptr (GError) error = NULL;
const char *remote_desktop_session_id;
GrdDBusScreenCast *screen_cast_proxy;
GVariantBuilder properties_builder;
@@ -744,15 +770,19 @@ on_remote_desktop_session_proxy_acquired (GObject *object,
grd_dbus_remote_desktop_session_proxy_new_finish (result, &error);
if (!session_proxy)
{
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
g_warning ("Failed to acquire remote desktop session proxy: %s\n",
error->message);
- g_error_free (error);
-
- grd_session_stop (session);
-
+ grd_session_stop (GRD_SESSION (user_data));
return;
}
+ session = GRD_SESSION (user_data);
+ priv = grd_session_get_instance_private (session);
+ klass = GRD_SESSION_GET_CLASS (session);
+
g_signal_connect (session_proxy, "closed",
G_CALLBACK (on_remote_desktop_session_closed),
session);
@@ -805,28 +835,31 @@ on_remote_desktop_session_created (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
- GrdSession *session = user_data;
- GrdSessionPrivate *priv = grd_session_get_instance_private (session);
GrdDBusRemoteDesktop *remote_desktop_proxy;
- g_autofree char *session_path = NULL;
+ GrdSession *session;
+ GrdSessionPrivate *priv;
GDBusConnection *connection;
- GError *error = NULL;
+ g_autofree char *session_path = NULL;
+ g_autoptr (GError) error = NULL;
- remote_desktop_proxy = grd_context_get_remote_desktop_proxy (priv->context);
+ remote_desktop_proxy = GRD_DBUS_REMOTE_DESKTOP (source_object);
if (!grd_dbus_remote_desktop_call_create_session_finish (remote_desktop_proxy,
&session_path,
res,
&error))
{
- g_warning ("Failed to start remote desktop session: %s\n", error->message);
- g_error_free (error);
-
- grd_session_stop (session);
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+ g_warning ("Failed to start remote desktop session: %s\n", error->message);
+ grd_session_stop (GRD_SESSION (user_data));
return;
}
+ session = GRD_SESSION (user_data);
+ priv = grd_session_get_instance_private (session);
connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (remote_desktop_proxy));
+
grd_dbus_remote_desktop_session_proxy_new (connection,
G_DBUS_PROXY_FLAGS_NONE,
MUTTER_REMOTE_DESKTOP_BUS_NAME,
@@ -871,7 +904,7 @@ grd_session_finalize (GObject *object)
g_assert (!priv->remote_desktop_session);
if (priv->cancellable)
- g_cancellable_cancel (priv->cancellable);
+ g_assert (g_cancellable_is_cancelled (priv->cancellable));
g_clear_object (&priv->cancellable);
G_OBJECT_CLASS (grd_session_parent_class)->finalize (object);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]