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>
This commit is contained in:
+19
-2
@@ -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;
|
||||
@@ -2133,13 +2134,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;
|
||||
}
|
||||
|
||||
@@ -2147,9 +2157,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);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -2555,6 +2570,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);
|
||||
|
||||
Reference in New Issue
Block a user