diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2017-02-13 15:03:20 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2017-02-13 20:31:20 +0100 |
commit | 1d41685f487a7d84846826d99fc99e3461ffce37 (patch) | |
tree | b4206b1cdcdf6d80f4f11babe2d81761fae1c1c0 | |
parent | 421713208bc3212d153906ad231a2e4b6b5ce6de (diff) |
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
-rw-r--r-- | src/mm-device.c | 34 |
1 files changed, 23 insertions, 11 deletions
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); } |