diff options
author | Ted Gould <ted@gould.cx> | 2011-02-01 09:53:50 -0600 |
---|---|---|
committer | Ted Gould <ted@gould.cx> | 2011-02-01 09:53:50 -0600 |
commit | 0ec3e4b5b199a27b20e371a4801d069e1d715c9d (patch) | |
tree | b411c7e7b0b2a135124997e517392d56f690b732 | |
parent | af210c6cac9ad3e7b3e658e2c8ca931a7b45cc66 (diff) | |
parent | c67f50916bd8cfe718ceed73ee95912d898df3d1 (diff) | |
download | ayatana-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.c | 66 |
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)); |