After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 734761 - Memory leak in implicit transition
Memory leak in implicit transition
Status: RESOLVED FIXED
Product: clutter
Classification: Platform
Component: ClutterActor
1.18.x
Other Linux
: Normal normal
: ---
Assigned To: clutter-maint
clutter-maint
Depends on:
Blocks:
 
 
Reported: 2014-08-14 04:08 UTC by Sunjin Yang
Modified: 2014-08-21 14:21 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Memory Leak Profile Graph (84.51 KB, image/svg+xml)
2014-08-14 04:08 UTC, Sunjin Yang
Details

Description Sunjin Yang 2014-08-14 04:08:37 UTC
Created attachment 283343 [details]
Memory Leak Profile Graph

I think that there is possible memory leak in implicit animation in Clutter 1.18.4 version.

To check run-time heap status, I have compiled following code and run with jemalloc profiling:


#include <clutter/clutter.h>

#define NUM_RECTANGLES   1000
#define RECTANGLE_WIDTH  20
#define RECTANGLE_HEIGHT 20

static ClutterActor *main_stage;

static void
animate_rectangle (ClutterActor *rect)
{
  gfloat max_width;
  gfloat max_height;
  gfloat x;
  gfloat y;

  max_width = clutter_actor_get_width (main_stage) - RECTANGLE_WIDTH;
  max_height = clutter_actor_get_height (main_stage) - RECTANGLE_WIDTH;
  x = g_random_double_range (0.0, max_width);
  y = g_random_double_range (0.0, max_height);

  clutter_actor_save_easing_state (rect);
  clutter_actor_set_easing_mode (rect, CLUTTER_LINEAR);
  clutter_actor_set_easing_duration (rect, 500);
  clutter_actor_set_position (rect, x, y);
  clutter_actor_set_opacity (rect, 128 - clutter_actor_get_opacity (rect) + 16);
  clutter_actor_restore_easing_state (rect);
}

static void
transition_stopped (ClutterActor *actor,
		    gchar        *name,
		    gboolean      is_finished,
		    gpointer      user_data)
{
  animate_rectangle (actor);
}

int
main (int    argc,
      char **argv)
{
  ClutterActor *stage;
  int i;

  if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
    return 1;

  stage = clutter_stage_new ();
  clutter_actor_show (stage);
  clutter_stage_set_title (CLUTTER_STAGE (stage), "Implict Animation Test");
  clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
  clutter_actor_set_background_color (stage, CLUTTER_COLOR_White);
  g_signal_connect (stage,
		    "destroy",
		    G_CALLBACK (clutter_main_quit),
		    NULL);
  main_stage = stage;

  for (i = 0; i < NUM_RECTANGLES; i++)
    {
      ClutterActor *rect;

      rect = clutter_actor_new ();
      clutter_actor_add_child (stage, rect);
      clutter_actor_set_size (rect, 20, 20);
      clutter_actor_set_background_color (rect, CLUTTER_COLOR_Red);
      clutter_actor_set_opacity (rect, 128);

      animate_rectangle (rect);

      g_signal_connect (rect, "transition-stopped::opacity", G_CALLBACK (transition_stopped), rect);
    }
  
  clutter_main ();

  return 0;
}


$ gcc -g -o anitest anitest.c `pkg-config --cflags --libs clutter-1.0`
$ G_DEBUG=gc-friendly \
  G_SLICE=always-malloc \
  LD_PRELOAD=/usr/lib/libjemalloc.so \
  MALLOC_CONF="prof:true,lg_prof_interval:30" \
  ./anitest

After some minutes, I stopped the program with Ctrl-C and created a profile graph(which is attached to this bug) like:


$ jemalloc-pprof --show_bytes --lines --svg --base=jeprof.7430.0.i0.heap anitest jeprof.7430.3.i3.heap > anitest-heap.svg


I don't know if this is the problem in my code or in Clutter. But after I modify Clutter code like following, memory leak is gone.


diff -uNrp clutter-1.18.4/clutter/clutter-actor.c clutter-1.18.4.new/clutter/clutter-actor.c
--- clutter-1.18.4/clutter/clutter-actor.c	2014-08-07 19:41:17.000000000 +0900
+++ clutter-1.18.4.new/clutter/clutter-actor.c	2014-08-14 13:06:23.840573543 +0900
@@ -18724,6 +18724,13 @@ on_transition_stopped (ClutterTransition
 
       g_signal_emit (actor, actor_signals[TRANSITIONS_COMPLETED], 0);
     }
+
+  if (clos->is_implicit ||
+      clutter_transition_get_remove_on_complete (transition))
+    {
+      /* we can release the reference here */
+      g_object_unref (transition);
+    }
 }


Any idea or suggestion?
Comment 1 Emmanuele Bassi (:ebassi) 2014-08-21 14:21:50 UTC
you're correct, and the patch is correct. thanks for the thorough investigation!

as a side note: the next time, make sure to attach a patch using `git-bz` or using `git format-patch`, so I can easily credit you appropriately, and get your contribution included more quickly.

I'll push this to the clutter-1.18 branch as well.

thanks again!