object: use weakref when advancing current transition
Fixes reference count leak when activating an object and transition fails
This commit is contained in:
@@ -143,6 +143,7 @@ struct _WpObjectPrivate
|
||||
WpObjectFeatures ft_active;
|
||||
GQueue *transitions; // element-type: WpFeatureActivationTransition*
|
||||
GSource *idle_advnc_source;
|
||||
GWeakRef ongoing_transition;
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -161,6 +162,7 @@ wp_object_init (WpObject * self)
|
||||
|
||||
g_weak_ref_init (&priv->core, NULL);
|
||||
priv->transitions = g_queue_new ();
|
||||
g_weak_ref_init (&priv->ongoing_transition, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -189,6 +191,7 @@ wp_object_finalize (GObject * object)
|
||||
g_warn_if_fail (g_queue_is_empty (priv->transitions));
|
||||
g_clear_pointer (&priv->transitions, g_queue_free);
|
||||
g_clear_pointer (&priv->idle_advnc_source, g_source_unref);
|
||||
g_weak_ref_clear (&priv->ongoing_transition);
|
||||
g_weak_ref_clear (&priv->core);
|
||||
|
||||
/* everything must have been deactivated in dispose() */
|
||||
@@ -309,17 +312,24 @@ static gboolean
|
||||
wp_object_advance_transitions (WpObject * self)
|
||||
{
|
||||
WpObjectPrivate *priv = wp_object_get_instance_private (self);
|
||||
WpTransition *t;
|
||||
|
||||
/* clear before advancing; a transition may need to schedule
|
||||
a new call to wp_object_advance_transitions() */
|
||||
g_clear_pointer (&priv->idle_advnc_source, g_source_unref);
|
||||
|
||||
while ((t = g_queue_peek_head (priv->transitions))) {
|
||||
wp_transition_advance (t);
|
||||
if (!wp_transition_get_completed (t))
|
||||
while (TRUE) {
|
||||
g_autoptr (WpTransition) t = g_weak_ref_get (&priv->ongoing_transition);
|
||||
if (t) {
|
||||
wp_transition_advance (t);
|
||||
if (!wp_transition_get_completed (t))
|
||||
break;
|
||||
}
|
||||
|
||||
if (g_queue_is_empty (priv->transitions))
|
||||
break;
|
||||
g_object_unref (g_queue_pop_head (priv->transitions));
|
||||
|
||||
g_weak_ref_set (&priv->ongoing_transition,
|
||||
g_queue_pop_head (priv->transitions));
|
||||
}
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
@@ -382,7 +392,7 @@ wp_object_activate_closure (WpObject * self,
|
||||
wp_transition_set_source_tag (transition, wp_object_activate);
|
||||
wp_transition_set_data (transition, GUINT_TO_POINTER (features), NULL);
|
||||
|
||||
g_queue_push_tail (priv->transitions, g_object_ref (transition));
|
||||
g_queue_push_tail (priv->transitions, transition);
|
||||
|
||||
if (!priv->idle_advnc_source) {
|
||||
wp_core_idle_add (core, &priv->idle_advnc_source,
|
||||
@@ -454,6 +464,7 @@ wp_object_update_features (WpObject * self, WpObjectFeatures activated,
|
||||
|
||||
WpObjectPrivate *priv = wp_object_get_instance_private (self);
|
||||
guint old_ft = priv->ft_active;
|
||||
g_autoptr (WpTransition) t = NULL;
|
||||
|
||||
priv->ft_active |= activated;
|
||||
priv->ft_active &= ~deactivated;
|
||||
@@ -464,7 +475,8 @@ wp_object_update_features (WpObject * self, WpObjectFeatures activated,
|
||||
g_object_notify (G_OBJECT (self), "active-features");
|
||||
}
|
||||
|
||||
if (!g_queue_is_empty (priv->transitions) && !priv->idle_advnc_source) {
|
||||
t = g_weak_ref_get (&priv->ongoing_transition);
|
||||
if ((t || !g_queue_is_empty (priv->transitions)) && !priv->idle_advnc_source) {
|
||||
g_autoptr (WpCore) core = g_weak_ref_get (&priv->core);
|
||||
g_return_if_fail (core != NULL);
|
||||
|
||||
|
Reference in New Issue
Block a user