[PATCH 09/10] daemon: release resources at shutdown
Peter Wu
peter at lekensteyn.nl
Wed Nov 26 03:21:16 PST 2014
This makes it easier to find real memory leaks with valgrind. After
calling the up_backend_unplug functions, you cannot restart it with
up_backend_coldplug since the lists are cleared.
Tested with Linux only (not on *BSD; dummy compiles).
https://bugs.freedesktop.org/show_bug.cgi?id=82659
---
src/dummy/up-backend.c | 20 ++++++++++++++++++++
src/freebsd/up-backend.c | 24 ++++++++++++++++++++++++
src/linux/up-backend.c | 27 +++++++++++++++++++++++++++
src/openbsd/up-backend.c | 16 ++++++++++++++++
src/up-backend.h | 1 +
src/up-daemon.c | 18 ++++++++++++++++++
src/up-daemon.h | 1 +
src/up-device-list.c | 31 +++++++++++++++++++++++++++++++
src/up-device-list.h | 2 ++
src/up-device.c | 16 ++++++++++++++++
src/up-device.h | 1 +
src/up-main.c | 1 +
12 files changed, 158 insertions(+)
diff --git a/src/dummy/up-backend.c b/src/dummy/up-backend.c
index 342111b..ad81b0b 100644
--- a/src/dummy/up-backend.c
+++ b/src/dummy/up-backend.c
@@ -129,6 +129,26 @@ up_backend_coldplug (UpBackend *backend, UpDaemon *daemon)
}
/**
+ * up_backend_unplug:
+ * @backend: The %UpBackend class instance
+ *
+ * Forget about all learned devices, effectively undoing up_backend_coldplug.
+ * Resources are released without emitting signals.
+ */
+void
+up_backend_unplug (UpBackend *backend)
+{
+ if (backend->priv->device_list != NULL) {
+ g_object_unref (backend->priv->device_list);
+ backend->priv->device_list = NULL;
+ }
+ if (backend->priv->daemon != NULL) {
+ g_object_unref (backend->priv->daemon);
+ backend->priv->daemon = NULL;
+ }
+}
+
+/**
* up_backend_get_critical_action:
* @backend: The %UpBackend class instance
*
diff --git a/src/freebsd/up-backend.c b/src/freebsd/up-backend.c
index ad54b9c..9fcd2b1 100644
--- a/src/freebsd/up-backend.c
+++ b/src/freebsd/up-backend.c
@@ -294,6 +294,30 @@ up_backend_coldplug (UpBackend *backend, UpDaemon *daemon)
}
/**
+ * up_backend_unplug:
+ * @backend: The %UpBackend class instance
+ *
+ * Forget about all learned devices, effectively undoing up_backend_coldplug.
+ * Resources are released without emitting signals.
+ */
+void
+up_backend_unplug (UpBackend *backend)
+{
+ if (backend->priv->poll_timer_id > 0) {
+ g_source_remove (backend->priv->poll_timer_id);
+ backend->priv->poll_timer_id = 0;
+ }
+ if (backend->priv->device_list != NULL) {
+ g_object_unref (backend->priv->device_list);
+ backend->priv->device_list = NULL;
+ }
+ if (backend->priv->daemon != NULL) {
+ g_object_unref (backend->priv->daemon);
+ backend->priv->daemon = NULL;
+ }
+}
+
+/**
* up_backend_get_critical_action:
* @backend: The %UpBackend class instance
*
diff --git a/src/linux/up-backend.c b/src/linux/up-backend.c
index f45ce29..b7a129d 100644
--- a/src/linux/up-backend.c
+++ b/src/linux/up-backend.c
@@ -340,6 +340,33 @@ up_backend_coldplug (UpBackend *backend, UpDaemon *daemon)
return TRUE;
}
+/**
+ * up_backend_unplug:
+ * @backend: The %UpBackend class instance
+ *
+ * Forget about all learned devices, effectively undoing up_backend_coldplug.
+ * Resources are released without emitting signals.
+ */
+void
+up_backend_unplug (UpBackend *backend)
+{
+ if (backend->priv->gudev_client != NULL) {
+ g_object_unref (backend->priv->gudev_client);
+ backend->priv->gudev_client = NULL;
+ }
+ if (backend->priv->device_list != NULL) {
+ g_object_unref (backend->priv->device_list);
+ backend->priv->device_list = NULL;
+ }
+ /* set in init, clear the list to remove reference to UpDaemon */
+ if (backend->priv->managed_devices != NULL)
+ up_device_list_clear (backend->priv->managed_devices, FALSE);
+ if (backend->priv->daemon != NULL) {
+ g_object_unref (backend->priv->daemon);
+ backend->priv->daemon = NULL;
+ }
+}
+
static gboolean
check_action_result (GVariant *result)
{
diff --git a/src/openbsd/up-backend.c b/src/openbsd/up-backend.c
index 807bb2f..20e86c0 100644
--- a/src/openbsd/up-backend.c
+++ b/src/openbsd/up-backend.c
@@ -150,6 +150,22 @@ up_backend_coldplug (UpBackend *backend, UpDaemon *daemon)
}
/**
+ * up_backend_unplug:
+ * @backend: The %UpBackend class instance
+ *
+ * Forget about all learned devices, effectively undoing up_backend_coldplug.
+ * Resources are released without emitting signals.
+ */
+void
+up_backend_unplug (UpBackend *backend)
+{
+ if (backend->priv->daemon != NULL) {
+ g_object_unref (backend->priv->daemon);
+ backend->priv->daemon = NULL;
+ }
+}
+
+/**
* up_backend_get_critical_action:
* @backend: The %UpBackend class instance
*
diff --git a/src/up-backend.h b/src/up-backend.h
index 7b3145c..213c0e1 100644
--- a/src/up-backend.h
+++ b/src/up-backend.h
@@ -69,6 +69,7 @@ void up_backend_test (gpointer user_data);
gboolean up_backend_coldplug (UpBackend *backend,
UpDaemon *daemon);
+void up_backend_unplug (UpBackend *backend);
void up_backend_take_action (UpBackend *backend);
const char *up_backend_get_critical_action (UpBackend *backend);
diff --git a/src/up-daemon.c b/src/up-daemon.c
index c795c93..f857c00 100644
--- a/src/up-daemon.c
+++ b/src/up-daemon.c
@@ -547,6 +547,24 @@ out:
}
/**
+ * up_daemon_shutdown:
+ *
+ * Stop the daemon, release all devices and resources.
+ **/
+void
+up_daemon_shutdown (UpDaemon *daemon)
+{
+ /* stop accepting new devices and clear backend state */
+ up_backend_unplug (daemon->priv->backend);
+
+ /* forget about discovered devices and release UpDaemon reference */
+ up_device_list_clear (daemon->priv->power_devices, TRUE);
+
+ /* release UpDaemon reference */
+ up_device_unplug (daemon->priv->display_device);
+}
+
+/**
* up_daemon_get_device_list:
**/
UpDeviceList *
diff --git a/src/up-daemon.h b/src/up-daemon.h
index 3392ad0..87857b3 100644
--- a/src/up-daemon.h
+++ b/src/up-daemon.h
@@ -72,6 +72,7 @@ guint up_daemon_get_number_devices_of_type (UpDaemon *daemon,
UpDeviceKind type);
UpDeviceList *up_daemon_get_device_list (UpDaemon *daemon);
gboolean up_daemon_startup (UpDaemon *daemon);
+void up_daemon_shutdown (UpDaemon *daemon);
void up_daemon_set_lid_is_closed (UpDaemon *daemon,
gboolean lid_is_closed);
void up_daemon_set_lid_is_present (UpDaemon *daemon,
diff --git a/src/up-device-list.c b/src/up-device-list.c
index da5555b..b95925a 100644
--- a/src/up-device-list.c
+++ b/src/up-device-list.c
@@ -130,6 +130,37 @@ up_device_list_remove (UpDeviceList *list, GObject *device)
}
/**
+ * up_device_list_remove_cb:
+ **/
+static gboolean
+up_device_list_remove_all_cb (gpointer key, gpointer value, gpointer user_data)
+{
+ return TRUE;
+}
+
+/**
+ * up_device_list_clear:
+ * @list: This class instance
+ * @unref_it: %TRUE if you own a reference to the objects and want to drop it.
+ *
+ * Clear the contents of this list.
+ **/
+void
+up_device_list_clear (UpDeviceList *list, gboolean unref_it)
+{
+ g_return_if_fail (UP_IS_DEVICE_LIST (list));
+
+ /* caller owns these objects, but wants to destroy them */
+ if (unref_it)
+ g_ptr_array_foreach (list->priv->array, (GFunc) g_object_unref, NULL);
+
+ /* remove all devices from the db */
+ g_hash_table_foreach_remove (list->priv->map_native_path_to_device,
+ up_device_list_remove_all_cb, NULL);
+ g_ptr_array_set_size (list->priv->array, 0);
+}
+
+/**
* up_device_list_get_array:
*
* This is quick to iterate when we don't have GObject's to resolve
diff --git a/src/up-device-list.h b/src/up-device-list.h
index 709c893..85a06bb 100644
--- a/src/up-device-list.h
+++ b/src/up-device-list.h
@@ -61,6 +61,8 @@ gboolean up_device_list_insert (UpDeviceList *list,
GObject *device);
gboolean up_device_list_remove (UpDeviceList *list,
GObject *device);
+void up_device_list_clear (UpDeviceList *list,
+ gboolean unref_it);
GPtrArray *up_device_list_get_array (UpDeviceList *list);
G_END_DECLS
diff --git a/src/up-device.c b/src/up-device.c
index 685be80..01b9f56 100644
--- a/src/up-device.c
+++ b/src/up-device.c
@@ -722,6 +722,22 @@ bail:
}
/**
+ * up_device_unplug:
+ *
+ * Initiates destruction of %UpDevice, undoing the effects of
+ * up_device_coldplug.
+ */
+void
+up_device_unplug (UpDevice *device)
+{
+ /* break circular dependency */
+ if (device->priv->daemon != NULL) {
+ g_object_unref (device->priv->daemon);
+ device->priv->daemon = NULL;
+ }
+}
+
+/**
* up_device_register_display_device:
**/
gboolean
diff --git a/src/up-device.h b/src/up-device.h
index 53415e7..a2d0b7e 100644
--- a/src/up-device.h
+++ b/src/up-device.h
@@ -75,6 +75,7 @@ UpDevice *up_device_new (void);
gboolean up_device_coldplug (UpDevice *device,
UpDaemon *daemon,
GObject *native);
+void up_device_unplug (UpDevice *device);
gboolean up_device_register_display_device (UpDevice *device,
UpDaemon *daemon);
UpDaemon *up_device_get_daemon (UpDevice *device);
diff --git a/src/up-main.c b/src/up-main.c
index c27cfb4..cb835b7 100644
--- a/src/up-main.c
+++ b/src/up-main.c
@@ -278,6 +278,7 @@ main (gint argc, gchar **argv)
/* wait for input or timeout */
g_main_loop_run (loop);
+ up_daemon_shutdown (daemon);
retval = 0;
out:
if (kbd_backlight != NULL)
--
2.1.3
More information about the devkit-devel
mailing list