From 1d41685f487a7d84846826d99fc99e3461ffce37 Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Mon, 13 Feb 2017 15:03:20 +0100 Subject: device: disconnect signal handlers when modem object removed Don't rely on the automatic disconnection of the signal as the last reference of the modem object may outlive the device object. Also, setup a common clear_modem() function to dispose the internal reference of the modem object, which will take care of the signal disconnection when required. https://lists.freedesktop.org/archives/modemmanager-devel/2017-February/003907.html --- src/mm-device.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/mm-device.c b/src/mm-device.c index 6750a0b1..803e64d3 100644 --- a/src/mm-device.c +++ b/src/mm-device.c @@ -71,6 +71,7 @@ struct _MMDevicePrivate { /* The Modem object for this device */ MMBaseModem *modem; + gulong modem_valid_id; /* When exported, a reference to the object manager */ GDBusObjectManagerServer *object_manager; @@ -293,6 +294,20 @@ export_modem (MMDevice *self) /*****************************************************************************/ +static void +clear_modem (MMDevice *self) +{ + if (self->priv->modem_valid_id) { + g_signal_handler_disconnect (self->priv->modem, self->priv->modem_valid_id); + self->priv->modem_valid_id = 0; + } + + /* Run dispose before unref-ing, in order to cleanup the SIM object, + * if any (which also holds a reference to the modem object) */ + g_object_run_dispose (G_OBJECT (self->priv->modem)); + g_clear_object (&(self->priv->modem)); +} + void mm_device_remove_modem (MMDevice *self) { @@ -300,11 +315,7 @@ mm_device_remove_modem (MMDevice *self) return; unexport_modem (self); - - /* Run dispose before unref-ing, in order to cleanup the SIM object, - * if any (which also holds a reference to the modem object) */ - g_object_run_dispose (G_OBJECT (self->priv->modem)); - g_clear_object (&(self->priv->modem)); + clear_modem (self); g_clear_object (&(self->priv->object_manager)); } @@ -391,10 +402,10 @@ mm_device_create_modem (MMDevice *self, self->priv->object_manager = g_object_ref (object_manager); /* We want to get notified when the modem becomes valid/invalid */ - g_signal_connect (self->priv->modem, - "notify::" MM_BASE_MODEM_VALID, - G_CALLBACK (modem_valid), - self); + self->priv->modem_valid_id = g_signal_connect (self->priv->modem, + "notify::" MM_BASE_MODEM_VALID, + G_CALLBACK (modem_valid), + self); } return !!self->priv->modem; @@ -582,7 +593,7 @@ set_property (GObject *object, self->priv->plugin = g_value_dup_object (value); break; case PROP_MODEM: - g_clear_object (&(self->priv->modem)); + clear_modem (self); self->priv->modem = g_value_dup_object (value); break; case PROP_HOTPLUGGED: @@ -635,7 +646,8 @@ dispose (GObject *object) g_clear_object (&(self->priv->plugin)); g_list_free_full (self->priv->port_probes, (GDestroyNotify)g_object_unref); g_list_free_full (self->priv->ignored_port_probes, (GDestroyNotify)g_object_unref); - g_clear_object (&(self->priv->modem)); + + clear_modem (self); G_OBJECT_CLASS (mm_device_parent_class)->dispose (object); } -- cgit v1.2.3-70-g09d2