aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dan@ioncontrol.co>2025-03-31 08:21:51 -0500
committerDan Williams <dan@ioncontrol.co>2025-05-08 15:40:25 -0500
commit0f97d90490dbacad3a40a372b3c6ac626e7c6082 (patch)
tree7cff5a6003db2a21c4f1eedb748f63ef872ef976
parent0cb1c1f157e2a4d2f75aeecc9874246359d0ca12 (diff)
broadband-modem: remove invalid idle handler during dispose
base_modem_invalid_idle() needs to keep a reference to the MMBaseModem until its done. But if the modem is cancelled during removal right before we're trying to forget about it, keeping that reference can prevent everything getting cleaned up by MMBaseModem's dispose() until after the mainloop has run again and all our removal operations are supposedly complete. MMDevice uses an explicit dispose() trigger that mitigates most of this (and requires it for other reasons, like breaking reference cycles between the modem and it's various child classes) but it's somewhat error-prone to keep the modem around if we don't really need to. Signed-off-by: Dan Williams <dan@ioncontrol.co>
-rw-r--r--src/mm-base-modem.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/src/mm-base-modem.c b/src/mm-base-modem.c
index 16f3e07b..7e142327 100644
--- a/src/mm-base-modem.c
+++ b/src/mm-base-modem.c
@@ -87,6 +87,7 @@ struct _MMBaseModemPrivate {
* should be done by the modem. */
GCancellable *cancellable;
gulong invalid_if_cancelled;
+ guint invalid_from_idle;
gchar *device;
gchar *physdev;
@@ -2162,13 +2163,22 @@ mm_base_modem_get_subsystem_device_id (MMBaseModem *self)
/*****************************************************************************/
+static void
+clear_invalid_from_idle (MMBaseModem *self)
+{
+ if (self->priv->invalid_from_idle)
+ g_source_remove (self->priv->invalid_from_idle);
+ self->priv->invalid_from_idle = 0;
+}
+
static gboolean
base_modem_invalid_idle (MMBaseModem *self)
{
+ clear_invalid_from_idle (self);
+
/* Ensure the modem is set invalid if we get the modem-wide cancellable
* cancelled */
mm_base_modem_set_valid (self, FALSE);
- g_object_unref (self);
return G_SOURCE_REMOVE;
}
@@ -2176,9 +2186,14 @@ static void
base_modem_cancelled (GCancellable *cancellable,
MMBaseModem *self)
{
+ clear_invalid_from_idle (self);
+
/* NOTE: Don't call set_valid() directly here, do it in an idle, and ensure
* that we pass a valid reference of the modem object as context. */
- g_idle_add ((GSourceFunc)base_modem_invalid_idle, g_object_ref (self));
+ self->priv->invalid_from_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+ (GSourceFunc)base_modem_invalid_idle,
+ g_object_ref (self),
+ (GDestroyNotify) g_object_unref);
}
/*****************************************************************************/
@@ -2584,6 +2599,8 @@ dispose (GObject *object)
g_cancellable_cancel (self->priv->cancellable);
g_clear_object (&self->priv->cancellable);
+ clear_invalid_from_idle (self);
+
g_clear_object (&self->priv->primary);
g_clear_object (&self->priv->secondary);
g_list_free_full (g_steal_pointer (&self->priv->data), g_object_unref);