diff options
author | Charles Kerr <charles.kerr@canonical.com> | 2014-07-24 22:51:03 -0500 |
---|---|---|
committer | Charles Kerr <charles.kerr@canonical.com> | 2014-07-24 22:51:03 -0500 |
commit | e9ba47b83251f40234059b1bd2bc25e30b5aa9b2 (patch) | |
tree | 7360e76ec4be3e968e95cdc6de1aa1a69c733916 /src | |
parent | b715352603062a4a4dbb5bc69388b1db632c34ae (diff) | |
download | ayatana-indicator-power-e9ba47b83251f40234059b1bd2bc25e30b5aa9b2.tar.gz ayatana-indicator-power-e9ba47b83251f40234059b1bd2bc25e30b5aa9b2.tar.bz2 ayatana-indicator-power-e9ba47b83251f40234059b1bd2bc25e30b5aa9b2.zip |
in notifier.c, fix potential callchain loop when closing a notification
Diffstat (limited to 'src')
-rw-r--r-- | src/notifier.c | 68 |
1 files changed, 42 insertions, 26 deletions
diff --git a/src/notifier.c b/src/notifier.c index 1ac7e32..dc3a186 100644 --- a/src/notifier.c +++ b/src/notifier.c @@ -90,55 +90,71 @@ static void set_power_level_property (IndicatorPowerNotifier*, ***/ static void +on_notify_notification_finalized (gpointer gself, GObject * dead) +{ + IndicatorPowerNotifier * const self = INDICATOR_POWER_NOTIFIER(gself); + priv_t * const p = get_priv(self); + g_return_if_fail ((void*)(p->notify_notification) == (void*)dead); + p->notify_notification = NULL; + set_is_warning_property (self, FALSE); +} + +static void notification_clear (IndicatorPowerNotifier * self) { priv_t * const p = get_priv(self); + NotifyNotification * nn; - if (p->notify_notification != NULL) + if ((nn = p->notify_notification)) { - set_is_warning_property (self, FALSE); + GError * error = NULL; + + g_object_weak_unref(G_OBJECT(nn), on_notify_notification_finalized, self); - notify_notification_clear_actions(p->notify_notification); - g_signal_handlers_disconnect_by_data(p->notify_notification, self); - g_clear_object(&p->notify_notification); + if (!notify_notification_close(nn, &error)) + { + g_warning("Unable to close notification: %s", error->message); + g_error_free(error); + } + + p->notify_notification = NULL; + set_is_warning_property(self, FALSE); } } static void notification_show(IndicatorPowerNotifier * self) { - priv_t * p; + priv_t * const p = get_priv(self); + gdouble pct; char * body; + NotifyNotification * nn; GError * error; - notification_clear (self); - - p = get_priv (self); + notification_clear(self); /* create the notification */ - body = g_strdup_printf(_("%.0f%% charge remaining"), - indicator_power_device_get_percentage(p->battery)); - p->notify_notification = notify_notification_new(_("Battery Low"), body, NULL); - notify_notification_set_hint(p->notify_notification, - HINT_INTERACTIVE, - g_variant_new_boolean(TRUE)); - g_signal_connect_swapped(p->notify_notification, "closed", - G_CALLBACK(notification_clear), self); - - /* show the notification */ + pct = indicator_power_device_get_percentage(p->battery); + body = g_strdup_printf(_("%.0f%% charge remaining"), pct); + nn = notify_notification_new(_("Battery Low"), body, NULL); + g_free (body); + notify_notification_set_hint(nn, HINT_INTERACTIVE, g_variant_new_boolean(TRUE)); + + /* if we can show it, keep it */ error = NULL; - notify_notification_show(p->notify_notification, &error); - if (error != NULL) + if (notify_notification_show(nn, &error)) { - g_critical("Unable to show snap decision for '%s': %s", body, error->message); - g_error_free(error); + p->notify_notification = nn; + g_signal_connect(nn, "closed", G_CALLBACK(g_object_unref), NULL); + g_object_weak_ref(G_OBJECT(nn), on_notify_notification_finalized, self); + set_is_warning_property(self, TRUE); } else { - set_is_warning_property (self, TRUE); + g_critical("Unable to show snap decision for '%s': %s", body, error->message); + g_error_free(error); + g_object_unref(nn); } - - g_free (body); } /*** |