aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Gould <ted@gould.cx>2011-02-01 09:53:50 -0600
committerTed Gould <ted@gould.cx>2011-02-01 09:53:50 -0600
commit0ec3e4b5b199a27b20e371a4801d069e1d715c9d (patch)
treeb411c7e7b0b2a135124997e517392d56f690b732
parentaf210c6cac9ad3e7b3e658e2c8ca931a7b45cc66 (diff)
parentc67f50916bd8cfe718ceed73ee95912d898df3d1 (diff)
downloadayatana-indicator-datetime-0ec3e4b5b199a27b20e371a4801d069e1d715c9d.tar.gz
ayatana-indicator-datetime-0ec3e4b5b199a27b20e371a4801d069e1d715c9d.tar.bz2
ayatana-indicator-datetime-0ec3e4b5b199a27b20e371a4801d069e1d715c9d.zip
Try to be better at cleaning up geoclue objects.
-rw-r--r--src/datetime-service.c66
1 files changed, 58 insertions, 8 deletions
diff --git a/src/datetime-service.c b/src/datetime-service.c
index 8a31940..9f795d1 100644
--- a/src/datetime-service.c
+++ b/src/datetime-service.c
@@ -40,6 +40,8 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
static void geo_create_client (GeoclueMaster * master, GeoclueMasterClient * client, gchar * path, GError * error, gpointer user_data);
static void setup_timer (void);
+static void geo_client_invalid (GeoclueMasterClient * client, gpointer user_data);
+static void geo_address_change (GeoclueMasterClient * client, gchar * a, gchar * b, gchar * c, gchar * d, gpointer user_data);
static IndicatorService * service = NULL;
static GMainLoop * mainloop = NULL;
@@ -384,6 +386,41 @@ geo_address_cb (GeoclueAddress * address, int timestamp, GHashTable * addy_data,
return;
}
+/* Clean up the reference we kept to the address and make sure to
+ drop the signals incase someone else has one. */
+static void
+geo_address_clean (void)
+{
+ if (geo_address == NULL) {
+ return;
+ }
+
+ g_signal_handlers_disconnect_by_func(G_OBJECT(geo_address), geo_address_cb, NULL);
+ g_object_unref(G_OBJECT(geo_address));
+
+ geo_address = NULL;
+
+ return;
+}
+
+/* Clean up and remove all signal handlers from the client as we
+ unreference it as well. */
+static void
+geo_client_clean (void)
+{
+ if (geo_master == NULL) {
+ return;
+ }
+
+ g_signal_handlers_disconnect_by_func(G_OBJECT(geo_master), geo_client_invalid, NULL);
+ g_signal_handlers_disconnect_by_func(G_OBJECT(geo_master), geo_address_change, NULL);
+ g_object_unref(G_OBJECT(geo_master));
+
+ geo_master = NULL;
+
+ return;
+}
+
/* Callback from creating the address */
static void
geo_create_address (GeoclueMasterClient * master, GeoclueAddress * address, GError * error, gpointer user_data)
@@ -393,6 +430,12 @@ geo_create_address (GeoclueMasterClient * master, GeoclueAddress * address, GErr
return;
}
+ /* We shouldn't have created a new address if we already had one
+ so this is a warning. But, it really is only a mem-leak so we
+ don't need to error out. */
+ g_warn_if_fail(geo_address == NULL);
+ geo_address_clean();
+
g_debug("Created Geoclue Address");
geo_address = address;
g_object_ref(G_OBJECT(geo_address));
@@ -420,10 +463,12 @@ geo_client_invalid (GeoclueMasterClient * client, gpointer user_data)
{
g_warning("Master client invalid, rebuilding.");
- if (geo_master != NULL) {
- g_object_unref(G_OBJECT(geo_master));
- }
- geo_master = NULL;
+ /* Client changes we can assume the address is now invalid so we
+ need to unreference the one we had. */
+ geo_address_clean();
+
+ /* And our master client is invalid */
+ geo_client_clean();
GeoclueMaster * master = geoclue_master_get_default();
geoclue_master_create_client_async(master, geo_create_client, NULL);
@@ -444,10 +489,9 @@ geo_address_change (GeoclueMasterClient * client, gchar * a, gchar * b, gchar *
{
g_warning("Address provider changed. Let's change");
- if (geo_address != NULL) {
- g_object_unref(G_OBJECT(geo_address));
- }
- geo_address = NULL;
+ /* If the address is supposed to have changed we need to drop the old
+ address before starting to get the new one. */
+ geo_address_clean();
geoclue_master_client_create_address_async(geo_master, geo_create_address, NULL);
@@ -470,6 +514,9 @@ geo_create_client (GeoclueMaster * master, GeoclueMasterClient * client, gchar *
geo_master = client;
g_object_ref(G_OBJECT(geo_master));
+ /* New client, make sure we don't have an address hanging on */
+ geo_address_clean();
+
geoclue_master_client_set_requirements_async(geo_master,
GEOCLUE_ACCURACY_LEVEL_REGION,
0,
@@ -537,6 +584,9 @@ main (int argc, char ** argv)
mainloop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(mainloop);
+ geo_address_clean();
+ geo_client_clean();
+
g_object_unref(G_OBJECT(master));
g_object_unref(G_OBJECT(dbus));
g_object_unref(G_OBJECT(service));