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

_______________________________________________
devkit-devel mailing list
devkit-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/devkit-devel

Reply via email to